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-01-12 23:22:32 +0300
committerJacques Lucke <jacques@blender.org>2021-01-12 23:22:32 +0300
commit1339e7c44f1f9a1c9bc5d6cb0a5702a6fe73515e (patch)
tree219481d8935a75ad6e2b97fe16193af3f763bb32
parentb66fcd83f6cef55a87dc9835129f8956fd6c6742 (diff)
parent719bea0d6d06be579edee2fc3d12a7828bb8e101 (diff)
Merge branch 'master' into experiment-point-distributiontemp-point-distribution-refactor-experiment
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py210
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.hh59
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/cryptomatte.cc65
-rw-r--r--source/blender/blenkernel/intern/cryptomatte_test.cc44
-rw-r--r--source/blender/compositor/CMakeLists.txt2
-rw-r--r--source/blender/compositor/intern/COM_MetaData.cpp71
-rw-r--r--source/blender/compositor/intern/COM_MetaData.h56
-rw-r--r--source/blender/compositor/intern/COM_SocketReader.h13
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cpp6
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp9
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.cpp33
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h6
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.cpp84
-rw-r--r--source/blender/compositor/operations/COM_RenderLayersProg.h2
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.cpp5
-rw-r--r--source/blender/compositor/operations/COM_SocketProxyOperation.h1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc8
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h4
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h12
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c6
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c4
-rw-r--r--source/blender/gpu/opengl/gl_backend.cc5
-rw-r--r--source/blender/imbuf/intern/IMB_indexer.h25
-rw-r--r--source/blender/imbuf/intern/anim_movie.c73
-rw-r--r--source/blender/imbuf/intern/indexer.c83
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.cc4
-rw-r--r--source/blender/nodes/geometry/node_geometry_util.hh2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc15
-rw-r--r--tests/python/CMakeLists.txt16
34 files changed, 730 insertions, 214 deletions
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 35fd7333cf4..495bf77b0e7 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -303,11 +303,11 @@ class CLIP_MT_masking_editor_menus(Menu):
if clip:
layout.menu("MASK_MT_select")
- layout.menu("CLIP_MT_clip") # XXX - remove?
+ layout.menu("CLIP_MT_clip")
layout.menu("MASK_MT_add")
layout.menu("MASK_MT_mask")
else:
- layout.menu("CLIP_MT_clip") # XXX - remove?
+ layout.menu("CLIP_MT_clip")
class CLIP_PT_clip_view_panel:
@@ -1330,10 +1330,17 @@ class CLIP_MT_clip(Menu):
layout.operator("clip.open")
if clip:
+ layout.operator("clip.set_scene_frames")
+ layout.operator("clip.set_center_principal")
layout.operator("clip.prefetch")
layout.operator("clip.reload")
layout.menu("CLIP_MT_proxy")
+ layout.separator()
+
+ layout.operator("clip.set_viewport_background")
+ layout.operator("clip.setup_tracking_scene")
+
class CLIP_MT_proxy(Menu):
bl_label = "Proxy"
@@ -1345,65 +1352,160 @@ class CLIP_MT_proxy(Menu):
layout.operator("clip.delete_proxy")
-class CLIP_MT_track(Menu):
- bl_label = "Track"
+class CLIP_MT_track_transform(Menu):
+ bl_label = "Transform"
def draw(self, _context):
layout = self.layout
- layout.operator("clip.clear_solution")
- layout.operator("clip.solve_camera")
+ layout.operator("transform.translate")
+ layout.operator("transform.rotate")
+ layout.operator("transform.resize")
+
- layout.separator()
- props = layout.operator("clip.clear_track_path", text="Clear After")
- props.clear_active = False
- props.action = 'REMAINED'
+class CLIP_MT_track_motion(Menu):
+ bl_label = "Track Motion"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ props = layout.operator("clip.track_markers", text="Backwards")
+ props.backwards = True
+ props.sequence = True
+
+ props = layout.operator("clip.track_markers", text="Frame Backwards")
+ props.backwards = True
+ props.sequence = False
+
+ props = layout.operator("clip.track_markers", text="Forwards")
+ props.backwards = False
+ props.sequence = True
+
+ props = layout.operator("clip.track_markers", text="Frame Forwards")
+ props.backwards = False
+ props.sequence = False
+
+
+class CLIP_MT_track_clear(Menu):
+ bl_label = "Clear"
- props = layout.operator("clip.clear_track_path", text="Clear Before")
+ def draw(self, _context):
+ layout = self.layout
+
+ props = layout.operator("clip.clear_track_path", text="Before")
props.clear_active = False
props.action = 'UPTO'
- props = layout.operator("clip.clear_track_path", text="Clear Track Path")
+ props = layout.operator("clip.clear_track_path", text="After")
+ props.clear_active = False
+ props.action = 'REMAINED'
+
+ props = layout.operator("clip.clear_track_path", text="Track Path")
props.clear_active = False
props.action = 'ALL'
layout.separator()
- layout.operator("clip.join_tracks")
- layout.separator()
+ layout.operator("clip.clear_solution", text="Solution")
+
+
+class CLIP_MT_track_refine(Menu):
+ bl_label = "Refine"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ props = layout.operator("clip.refine_markers", text="Backwards")
+ props.backwards = True
+
+ props = layout.operator("clip.refine_markers", text="Fowards")
+ props.backwards = False
+
+
+class CLIP_MT_track_animation(Menu):
+ bl_label = "Animation"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("clip.keyframe_insert")
+ layout.operator("clip.keyframe_delete")
+
+
+class CLIP_MT_track_visibility(Menu):
+ bl_label = "Show/Hide"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("clip.hide_tracks_clear")
+ layout.operator("clip.hide_tracks", text="Hide Selected").unselected = False
+ layout.operator("clip.hide_tracks", text="Hide Unselected").unselected = True
+
+
+class CLIP_MT_track_cleanup(Menu):
+ bl_label = "Clean Up"
+
+ def draw(self, _context):
+ layout = self.layout
+
layout.operator("clip.clean_tracks")
+ layout.operator("clip.filter_tracks")
+
+
+class CLIP_MT_track(Menu):
+ bl_label = "Track"
+
+ def draw(self, context):
+ layout = self.layout
+
+ clip = context.space_data.clip
+ tracking_object = clip.tracking.objects.active
+
+ layout.menu("CLIP_MT_track_transform")
+ layout.menu("CLIP_MT_track_motion")
+ layout.menu("CLIP_MT_track_clear")
+ layout.menu("CLIP_MT_track_refine")
layout.separator()
- layout.operator("clip.copy_tracks")
- layout.operator("clip.paste_tracks")
+
+ layout.operator("clip.add_marker_move", text="Add Marker")
+ layout.operator("clip.detect_features")
+ layout.operator("clip.create_plane_track")
layout.separator()
- props = layout.operator("clip.track_markers", text="Track Frame Backwards")
- props.backwards = True
- props.sequence = False
- props = layout.operator("clip.track_markers", text="Track Backwards")
- props.backwards = True
- props.sequence = True
+ layout.operator("clip.solve_camera",
+ text="Solve Camera Motion" if tracking_object.is_camera
+ else "Solve Object Motion")
- props = layout.operator("clip.track_markers", text="Track Forwards")
- props.backwards = False
- props.sequence = True
+ layout.separator()
- props = layout.operator("clip.track_markers", text="Track Frame Forwards")
- props.backwards = False
- props.sequence = False
+ layout.operator("clip.join_tracks")
layout.separator()
- layout.operator("clip.delete_track")
- layout.operator("clip.delete_marker")
+
+ layout.operator("clip.copy_tracks", icon='COPYDOWN')
+ layout.operator("clip.paste_tracks", icon='PASTEDOWN')
layout.separator()
- layout.operator("clip.add_marker_move")
+
+ layout.operator("clip.track_settings_as_default", text="Copy Settings to Defaults")
+ layout.operator("clip.track_settings_to_track", text="Apply Default Settings")
+
+ layout.separator()
+
+ layout.menu("CLIP_MT_track_animation")
layout.separator()
+
layout.menu("CLIP_MT_track_visibility")
- layout.menu("CLIP_MT_track_transform")
+ layout.menu("CLIP_MT_track_cleanup")
+
+ layout.separator()
+
+ layout.operator("clip.delete_track")
+ layout.operator("clip.delete_marker")
class CLIP_MT_reconstruction(Menu):
@@ -1420,6 +1522,7 @@ class CLIP_MT_reconstruction(Menu):
layout.operator("clip.set_axis", text="Set Y Axis").axis = 'Y'
layout.operator("clip.set_scale")
+ layout.operator("clip.apply_solution_scale")
layout.separator()
@@ -1427,25 +1530,13 @@ class CLIP_MT_reconstruction(Menu):
layout.operator("clip.bundles_to_mesh")
-class CLIP_MT_track_visibility(Menu):
- bl_label = "Show/Hide"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator("clip.hide_tracks_clear")
- layout.operator("clip.hide_tracks", text="Hide Selected").unselected = False
- layout.operator("clip.hide_tracks", text="Hide Unselected").unselected = True
-
-
-class CLIP_MT_track_transform(Menu):
- bl_label = "Transform"
+class CLIP_MT_select_grouped(Menu):
+ bl_label = "Select Grouped"
def draw(self, _context):
layout = self.layout
- layout.operator("transform.translate")
- layout.operator("transform.resize")
+ layout.operator_enum("clip.select_grouped", "group")
class CLIP_MT_select(Menu):
@@ -1459,21 +1550,15 @@ class CLIP_MT_select(Menu):
layout.separator()
- layout.operator("clip.select_all"
- ).action = 'TOGGLE'
- layout.operator("clip.select_all",
- text="Inverse").action = 'INVERT'
+ layout.operator("clip.select_all").action = 'TOGGLE'
+ layout.operator("clip.select_all", text="Inverse").action = 'INVERT'
layout.menu("CLIP_MT_select_grouped")
+ layout.separator()
-class CLIP_MT_select_grouped(Menu):
- bl_label = "Select Grouped"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator_enum("clip.select_grouped", "group")
+ layout.operator("clip.stabilize_2d_select")
+ layout.operator("clip.stabilize_2d_rotation_select")
class CLIP_MT_tracking_context_menu(Menu):
@@ -1746,7 +1831,6 @@ classes = (
CLIP_PT_display,
CLIP_PT_clip_display,
CLIP_PT_marker_display,
- CLIP_MT_track,
CLIP_MT_tracking_editor_menus,
CLIP_MT_masking_editor_menus,
CLIP_PT_track,
@@ -1786,8 +1870,14 @@ classes = (
CLIP_MT_clip,
CLIP_MT_proxy,
CLIP_MT_reconstruction,
- CLIP_MT_track_visibility,
+ CLIP_MT_track,
CLIP_MT_track_transform,
+ CLIP_MT_track_motion,
+ CLIP_MT_track_clear,
+ CLIP_MT_track_refine,
+ CLIP_MT_track_animation,
+ CLIP_MT_track_visibility,
+ CLIP_MT_track_cleanup,
CLIP_MT_select,
CLIP_MT_select_grouped,
CLIP_MT_tracking_context_menu,
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
new file mode 100644
index 00000000000..892f228187e
--- /dev/null
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -0,0 +1,59 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#pragma once
+
+#include <string>
+
+#include "BLI_string_ref.hh"
+
+namespace blender {
+
+/* Format to a cryptomatte meta data key.
+ *
+ * Cryptomatte stores meta data. The keys are formatted containing a hash that
+ * is generated from its layer name.
+ *
+ * The output of this function is:
+ * 'cryptomatte/{hash of layer_name}/{key_name}'.
+ */
+std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name,
+ const StringRefNull key_name);
+
+/* Extract the cryptomatte layer name from the given `render_pass_name`.
+ *
+ * Cryptomatte passes are formatted with a trailing number for storing multiple samples that belong
+ * to the same cryptomatte layer. This function would remove the trailing numbers to determine the
+ * cryptomatte layer name.
+ *
+ * # Example
+ *
+ * A render_pass_name could be 'View Layer.CryptoMaterial02'. The cryptomatte layer would be 'View
+ * Layer.CryptoMaterial'.
+ *
+ * NOTE: The return type is a substring of `render_pass_name` and therefore cannot outlive the
+ * `render_pass_name` internal data.
+ */
+StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name);
+
+} // namespace blender
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 574d70bf456..5021736dbfe 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -731,6 +731,7 @@ add_dependencies(bf_blenkernel bf_dna)
if(WITH_GTESTS)
set(TEST_SRC
intern/armature_test.cc
+ intern/cryptomatte_test.cc
intern/fcurve_test.cc
intern/lattice_deform_test.cc
intern/layer_test.cc
diff --git a/source/blender/blenkernel/intern/cryptomatte.cc b/source/blender/blenkernel/intern/cryptomatte.cc
index 1dd71dacc46..7ddc1474e09 100644
--- a/source/blender/blenkernel/intern/cryptomatte.cc
+++ b/source/blender/blenkernel/intern/cryptomatte.cc
@@ -22,6 +22,7 @@
*/
#include "BKE_cryptomatte.h"
+#include "BKE_cryptomatte.hh"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -43,6 +44,7 @@
#include <iomanip>
#include <sstream>
#include <string>
+#include <string_view>
enum CryptomatteLayerState {
EMPTY,
@@ -299,15 +301,15 @@ static uint32_t cryptomatte_determine_identifier(const std::string name)
return BLI_hash_mm3(reinterpret_cast<const unsigned char *>(name.c_str()), name.length(), 0);
}
-static std::string cryptomatte_determine_prefix(const std::string name)
+static void add_render_result_meta_data(RenderResult *render_result,
+ const blender::StringRef layer_name,
+ const blender::StringRefNull key_name,
+ const blender::StringRefNull value)
{
- std::stringstream stream;
- const uint32_t render_pass_identifier = cryptomatte_determine_identifier(name);
- stream << "cryptomatte/";
- stream << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex
- << render_pass_identifier;
- stream << "/";
- return stream.str();
+ BKE_render_result_stamp_data(
+ render_result,
+ blender::BKE_cryptomatte_meta_data_key(layer_name, key_name).c_str(),
+ value.data());
}
void BKE_cryptomatte_store_metadata(struct CryptomatteSession *session,
@@ -335,12 +337,47 @@ void BKE_cryptomatte_store_metadata(struct CryptomatteSession *session,
const std::string manifest = layer->manifest_get_string();
const std::string name = cryptomatte_determine_name(view_layer, cryptomatte_layer_name);
- const std::string prefix = cryptomatte_determine_prefix(name);
/* Store the meta data into the render result. */
- BKE_render_result_stamp_data(render_result, (prefix + "name").c_str(), name.c_str());
- BKE_render_result_stamp_data(render_result, (prefix + "hash").c_str(), "MurmurHash3_32");
- BKE_render_result_stamp_data(
- render_result, (prefix + "conversion").c_str(), "uint32_to_float32");
- BKE_render_result_stamp_data(render_result, (prefix + "manifest").c_str(), manifest.c_str());
+ add_render_result_meta_data(render_result, name, "name", name);
+ add_render_result_meta_data(render_result, name, "hash", "MurmurHash3_32");
+ add_render_result_meta_data(render_result, name, "conversion", "uint32_to_float32");
+ add_render_result_meta_data(render_result, name, "manifest", manifest);
+}
+
+namespace blender {
+
+/* Return the hash of the given cryptomatte layer name.
+ *
+ * The cryptomatte specification limits the hash to 7 characters.
+ * The 7 position limitation solves issues when using cryptomatte together with OpenEXR.
+ * The specification suggests to use the first 7 chars of the hashed layer_name.
+ */
+static std::string cryptomatte_layer_name_hash(const StringRef layer_name)
+{
+ std::stringstream stream;
+ const uint32_t render_pass_identifier = cryptomatte_determine_identifier(layer_name);
+ stream << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex
+ << render_pass_identifier;
+ return stream.str().substr(0, 7);
+}
+
+std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name, const StringRefNull key_name)
+{
+ return "cryptomatte/" + cryptomatte_layer_name_hash(layer_name) + "/" + key_name;
}
+
+/* Extracts the cryptomatte name from a render pass name.
+ *
+ * Example: A render pass could be named `CryptoObject00`. This
+ * function would remove the trailing digits and return `CryptoObject`. */
+StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name)
+{
+ int64_t last_token = render_pass_name.size();
+ while (last_token > 0 && std::isdigit(render_pass_name[last_token - 1])) {
+ last_token -= 1;
+ }
+ return render_pass_name.substr(0, last_token);
+}
+
+} // namespace blender
diff --git a/source/blender/blenkernel/intern/cryptomatte_test.cc b/source/blender/blenkernel/intern/cryptomatte_test.cc
new file mode 100644
index 00000000000..3773b2b3bf9
--- /dev/null
+++ b/source/blender/blenkernel/intern/cryptomatte_test.cc
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ */
+#include "testing/testing.h"
+
+#include "BKE_cryptomatte.hh"
+
+namespace blender::bke::tests {
+
+TEST(cryptomatte, meta_data_key)
+{
+ ASSERT_EQ("cryptomatte/c7dbf5e/key",
+ BKE_cryptomatte_meta_data_key("ViewLayer.CryptoMaterial", "key"));
+ ASSERT_EQ("cryptomatte/b990b65/𝓴𝓮𝔂",
+ BKE_cryptomatte_meta_data_key("𝖚𝖓𝖎𝖈𝖔𝖉𝖊.CryptoMaterial", "𝓴𝓮𝔂"));
+}
+
+TEST(cryptomatte, extract_layer_name)
+{
+ ASSERT_EQ("ViewLayer.CryptoMaterial",
+ BKE_cryptomatte_extract_layer_name("ViewLayer.CryptoMaterial00"));
+ ASSERT_EQ("𝖚𝖓𝖎𝖈𝖔𝖉𝖊", BKE_cryptomatte_extract_layer_name("𝖚𝖓𝖎𝖈𝖔𝖉𝖊13"));
+ ASSERT_EQ("NoTrailingSampleNumber",
+ BKE_cryptomatte_extract_layer_name("NoTrailingSampleNumber"));
+ ASSERT_EQ("W1thM1dd13Numb3rs", BKE_cryptomatte_extract_layer_name("W1thM1dd13Numb3rs09"));
+ ASSERT_EQ("", BKE_cryptomatte_extract_layer_name("0123"));
+ ASSERT_EQ("", BKE_cryptomatte_extract_layer_name(""));
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 19eeb90c822..a226b009ec9 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -71,6 +71,8 @@ set(SRC
intern/COM_MemoryBuffer.h
intern/COM_MemoryProxy.cpp
intern/COM_MemoryProxy.h
+ intern/COM_MetaData.cpp
+ intern/COM_MetaData.h
intern/COM_Node.cpp
intern/COM_Node.h
intern/COM_NodeConverter.cpp
diff --git a/source/blender/compositor/intern/COM_MetaData.cpp b/source/blender/compositor/intern/COM_MetaData.cpp
new file mode 100644
index 00000000000..2b75947ff89
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MetaData.cpp
@@ -0,0 +1,71 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#include "COM_MetaData.h"
+
+#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
+
+#include "RE_pipeline.h"
+
+#include <string_view>
+
+void MetaData::add(const blender::StringRef key, const blender::StringRef value)
+{
+ entries_.add(key, value);
+}
+
+void MetaData::addCryptomatteEntry(const blender::StringRef layer_name,
+ const blender::StringRefNull key,
+ const blender::StringRef value)
+{
+ add(blender::BKE_cryptomatte_meta_data_key(layer_name, key), value);
+}
+
+/* Replace the hash neutral cryptomatte keys with hashed versions.
+ *
+ * When a conversion happens it will also add the cryptomatte name key with the given
+ * `layer_name`.*/
+void MetaData::replaceHashNeutralCryptomatteKeys(const blender::StringRef layer_name)
+{
+ std::string cryptomatte_hash = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_HASH, "");
+ std::string cryptomatte_conversion = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_CONVERSION,
+ "");
+ std::string cryptomatte_manifest = entries_.pop_default(META_DATA_KEY_CRYPTOMATTE_MANIFEST, "");
+
+ if (cryptomatte_hash.length() || cryptomatte_conversion.length() ||
+ cryptomatte_manifest.length()) {
+ addCryptomatteEntry(layer_name, "name", layer_name);
+ }
+ if (cryptomatte_hash.length()) {
+ addCryptomatteEntry(layer_name, "hash", cryptomatte_hash);
+ }
+ if (cryptomatte_conversion.length()) {
+ addCryptomatteEntry(layer_name, "conversion", cryptomatte_conversion);
+ }
+ if (cryptomatte_manifest.length()) {
+ addCryptomatteEntry(layer_name, "manifest", cryptomatte_manifest);
+ }
+}
+
+void MetaData::addToRenderResult(RenderResult *render_result) const
+{
+ for (blender::Map<std::string, std::string>::Item entry : entries_.items()) {
+ BKE_render_result_stamp_data(render_result, entry.key.c_str(), entry.value.c_str());
+ }
+}
diff --git a/source/blender/compositor/intern/COM_MetaData.h b/source/blender/compositor/intern/COM_MetaData.h
new file mode 100644
index 00000000000..22988b0b7ee
--- /dev/null
+++ b/source/blender/compositor/intern/COM_MetaData.h
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "BLI_map.hh"
+
+#include "MEM_guardedalloc.h"
+
+/* Forward declarations. */
+struct StampData;
+struct RenderResult;
+
+/* Cryptomatte includes hash in its meta data keys. The hash is generated from the render
+ * layer/pass name. Compositing happens without the knowledge of the original layer and pass. The
+ * next keys are used to transfer the cryptomatte meta data in a neutral way. The file output node
+ * will generate a hash based on the layer name configured by the user.
+ *
+ * The `{hash}` has no special meaning except to make sure that the meta data stays unique. */
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_HASH("cryptomatte/{hash}/hash");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_CONVERSION("cryptomatte/{hash}/conversion");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_MANIFEST("cryptomatte/{hash}/manifest");
+constexpr blender::StringRef META_DATA_KEY_CRYPTOMATTE_NAME("cryptomatte/{hash}/name");
+
+class MetaData {
+ private:
+ blender::Map<std::string, std::string> entries_;
+ void addCryptomatteEntry(const blender::StringRef layer_name,
+ const blender::StringRefNull key,
+ const blender::StringRef value);
+
+ public:
+ void add(const blender::StringRef key, const blender::StringRef value);
+ void replaceHashNeutralCryptomatteKeys(const blender::StringRef layer_name);
+ void addToRenderResult(RenderResult *render_result) const;
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("COM:MetaData")
+#endif
+};
diff --git a/source/blender/compositor/intern/COM_SocketReader.h b/source/blender/compositor/intern/COM_SocketReader.h
index ee2a6e0e1bf..7c4132efe60 100644
--- a/source/blender/compositor/intern/COM_SocketReader.h
+++ b/source/blender/compositor/intern/COM_SocketReader.h
@@ -19,8 +19,12 @@
#pragma once
#include "BLI_rect.h"
+#include "COM_MetaData.h"
#include "COM_defines.h"
+#include <memory>
+#include <optional>
+
#ifdef WITH_CXX_GUARDEDALLOC
# include "MEM_guardedalloc.h"
#endif
@@ -32,6 +36,7 @@ typedef enum PixelSampler {
} PixelSampler;
class MemoryBuffer;
+
/**
* \brief Helper class for reading socket data.
* Only use this class for dispatching (un-ary and n-ary) executions.
@@ -134,6 +139,14 @@ class SocketReader {
return this->m_height;
}
+ /* Return the meta data associated with this branch.
+ *
+ * The return parameter holds an instance or is an nullptr. */
+ virtual std::unique_ptr<MetaData> getMetaData() const
+ {
+ return std::unique_ptr<MetaData>();
+ }
+
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("COM:SocketReader")
#endif
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cpp b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
index 09528e09f1f..e0cff1de276 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cpp
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cpp
@@ -50,7 +50,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
OutputOpenExrMultiLayerOperation *outputOperation;
if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
- outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(context.getRenderData(),
+ outputOperation = new OutputOpenExrMultiLayerMultiViewOperation(context.getScene(),
+ context.getRenderData(),
context.getbNodeTree(),
storage->base_path,
storage->format.exr_codec,
@@ -58,7 +59,8 @@ void OutputFileNode::convertToOperations(NodeConverter &converter,
context.getViewName());
}
else {
- outputOperation = new OutputOpenExrMultiLayerOperation(context.getRenderData(),
+ outputOperation = new OutputOpenExrMultiLayerOperation(context.getScene(),
+ context.getRenderData(),
context.getbNodeTree(),
storage->base_path,
storage->format.exr_codec,
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
index 21d9177ddd5..0b732357c92 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp
@@ -143,13 +143,14 @@ void OutputOpenExrSingleLayerMultiViewOperation::deinitExecution()
/************************************ OpenEXR Multilayer Multiview *******************************/
OutputOpenExrMultiLayerMultiViewOperation::OutputOpenExrMultiLayerMultiViewOperation(
+ const Scene *scene,
const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
bool exr_half_float,
const char *viewName)
- : OutputOpenExrMultiLayerOperation(rd, tree, path, exr_codec, exr_half_float, viewName)
+ : OutputOpenExrMultiLayerOperation(scene, rd, tree, path, exr_codec, exr_half_float, viewName)
{
}
@@ -195,12 +196,16 @@ void *OutputOpenExrMultiLayerMultiViewOperation::get_handle(const char *filename
BLI_make_existing_file(filename);
/* prepare the file with all the channels for the header */
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, nullptr) == 0) {
+ StampData *stamp_data = createStampData();
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data) ==
+ 0) {
printf("Error Writing Multilayer Multiview Openexr\n");
IMB_exr_close(exrhandle);
+ BKE_stamp_data_free(stamp_data);
}
else {
IMB_exr_clear_channels(exrhandle);
+ BKE_stamp_data_free(stamp_data);
return exrhandle;
}
}
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
index 1deaf121173..bc057355cef 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -48,7 +48,8 @@ class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOpera
class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation {
private:
public:
- OutputOpenExrMultiLayerMultiViewOperation(const RenderData *rd,
+ OutputOpenExrMultiLayerMultiViewOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
index 2676ab1b9ca..216b754f676 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp
@@ -18,12 +18,15 @@
#include "COM_OutputFileOperation.h"
+#include "COM_MetaData.h"
+
#include <cstring>
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BKE_cryptomatte.hh"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -36,6 +39,8 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "RE_pipeline.h"
+
void add_exr_channels(void *exrhandle,
const char *layerName,
const DataType datatype,
@@ -299,13 +304,15 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name_, DataType datatype_, bo
this->imageInput = nullptr;
}
-OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(const RenderData *rd,
+OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
bool exr_half_float,
const char *viewName)
{
+ this->m_scene = scene;
this->m_rd = rd;
this->m_tree = tree;
@@ -323,6 +330,26 @@ void OutputOpenExrMultiLayerOperation::add_layer(const char *name,
this->m_layers.push_back(OutputOpenExrLayer(name, datatype, use_layer));
}
+StampData *OutputOpenExrMultiLayerOperation::createStampData() const
+{
+ /* StampData API doesn't provide functions to modify an instance without having a RenderResult.
+ */
+ RenderResult render_result;
+ StampData *stamp_data = BKE_stamp_info_from_scene_static(m_scene);
+ render_result.stamp_data = stamp_data;
+ for (int i = 0; i < this->m_layers.size(); i++) {
+ const OutputOpenExrLayer *layer = &this->m_layers[i];
+ std::unique_ptr<MetaData> meta_data = layer->imageInput->getMetaData();
+ if (meta_data) {
+ blender::StringRef layer_name = blender::BKE_cryptomatte_extract_layer_name(
+ blender::StringRef(layer->name, BLI_strnlen(layer->name, sizeof(layer->name))));
+ meta_data->replaceHashNeutralCryptomatteKeys(layer_name);
+ meta_data->addToRenderResult(&render_result);
+ }
+ }
+ return stamp_data;
+}
+
void OutputOpenExrMultiLayerOperation::initExecution()
{
for (unsigned int i = 0; i < this->m_layers.size(); i++) {
@@ -386,7 +413,8 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
}
/* when the filename has no permissions, this can fail */
- if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, nullptr)) {
+ StampData *stamp_data = createStampData();
+ if (IMB_exr_begin_write(exrhandle, filename, width, height, this->m_exr_codec, stamp_data)) {
IMB_exr_write_channels(exrhandle);
}
else {
@@ -404,5 +432,6 @@ void OutputOpenExrMultiLayerOperation::deinitExecution()
this->m_layers[i].imageInput = nullptr;
}
+ BKE_stamp_data_free(stamp_data);
}
}
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index b2454e17e3f..915d59599e2 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -91,6 +91,7 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
protected:
typedef std::vector<OutputOpenExrLayer> LayerList;
+ const Scene *m_scene;
const RenderData *m_rd;
const bNodeTree *m_tree;
@@ -100,8 +101,11 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation {
LayerList m_layers;
const char *m_viewName;
+ StampData *createStampData() const;
+
public:
- OutputOpenExrMultiLayerOperation(const RenderData *rd,
+ OutputOpenExrMultiLayerOperation(const Scene *scene,
+ const RenderData *rd,
const bNodeTree *tree,
const char *path,
char exr_codec,
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
index 11f64aa4d6a..2a0a6e33b6a 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp
@@ -18,8 +18,16 @@
#include "COM_RenderLayersProg.h"
+#include "COM_MetaData.h"
+
+#include "BKE_cryptomatte.hh"
+#include "BKE_image.h"
#include "BKE_scene.h"
+
#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_ref.hh"
+
#include "DNA_scene_types.h"
#include "RE_pipeline.h"
@@ -209,6 +217,82 @@ void RenderLayersProg::determineResolution(unsigned int resolution[2],
}
}
+struct CallbackData {
+ std::unique_ptr<MetaData> meta_data;
+ std::string hash_key;
+ std::string conversion_key;
+ std::string manifest_key;
+
+ void addMetaData(blender::StringRef key, blender::StringRefNull value)
+ {
+ if (!meta_data) {
+ meta_data = std::make_unique<MetaData>();
+ }
+ meta_data->add(key, value);
+ }
+
+ void setCryptomatteKeys(blender::StringRef cryptomatte_layer_name)
+ {
+ manifest_key = blender::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name, "manifest");
+ hash_key = blender::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name, "hash");
+ conversion_key = blender::BKE_cryptomatte_meta_data_key(cryptomatte_layer_name, "conversion");
+ }
+};
+
+/* C type callback function (StampCallback). */
+static void extract_cryptomatte_meta_data(void *_data,
+ const char *propname,
+ char *propvalue,
+ int UNUSED(len))
+{
+ CallbackData *data = static_cast<CallbackData *>(_data);
+ blender::StringRefNull key(propname);
+ if (key == data->hash_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_HASH, propvalue);
+ }
+ else if (key == data->conversion_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_CONVERSION, propvalue);
+ }
+ else if (key == data->manifest_key) {
+ data->addMetaData(META_DATA_KEY_CRYPTOMATTE_MANIFEST, propvalue);
+ }
+}
+
+std::unique_ptr<MetaData> RenderLayersProg::getMetaData() const
+{
+ Scene *scene = this->getScene();
+ Render *re = (scene) ? RE_GetSceneRender(scene) : nullptr;
+ RenderResult *rr = nullptr;
+ CallbackData callback_data = {nullptr};
+
+ if (re) {
+ rr = RE_AcquireResultRead(re);
+ }
+
+ if (rr && rr->stamp_data) {
+ ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, getLayerId());
+ if (view_layer) {
+ std::string full_layer_name = std::string(
+ view_layer->name,
+ BLI_strnlen(view_layer->name, sizeof(view_layer->name))) +
+ "." + m_passName;
+ blender::StringRef cryptomatte_layer_name = blender::BKE_cryptomatte_extract_layer_name(
+ full_layer_name);
+ callback_data.setCryptomatteKeys(cryptomatte_layer_name);
+
+ BKE_stamp_info_callback(
+ &callback_data, rr->stamp_data, extract_cryptomatte_meta_data, false);
+ }
+ }
+
+ if (re) {
+ RE_ReleaseResult(re);
+ re = nullptr;
+ }
+
+ return std::move(callback_data.meta_data);
+}
+
/* ******** Render Layers AO Operation ******** */
void RenderLayersAOOperation::executePixelSampled(float output[4],
float x,
diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h
index abfcac1f80d..ec98969b223 100644
--- a/source/blender/compositor/operations/COM_RenderLayersProg.h
+++ b/source/blender/compositor/operations/COM_RenderLayersProg.h
@@ -121,6 +121,8 @@ class RenderLayersProg : public NodeOperation {
void initExecution();
void deinitExecution();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
+
+ std::unique_ptr<MetaData> getMetaData() const override;
};
class RenderLayersAOOperation : public RenderLayersProg {
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
index baeb2f44303..53f5fea8795 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.cpp
@@ -24,3 +24,8 @@ SocketProxyOperation::SocketProxyOperation(DataType type, bool use_conversion)
this->addInputSocket(type);
this->addOutputSocket(type);
}
+
+std::unique_ptr<MetaData> SocketProxyOperation::getMetaData() const
+{
+ return this->getInputSocket(0)->getReader()->getMetaData();
+}
diff --git a/source/blender/compositor/operations/COM_SocketProxyOperation.h b/source/blender/compositor/operations/COM_SocketProxyOperation.h
index 22c144598f6..435083f5008 100644
--- a/source/blender/compositor/operations/COM_SocketProxyOperation.h
+++ b/source/blender/compositor/operations/COM_SocketProxyOperation.h
@@ -41,6 +41,7 @@ class SocketProxyOperation : public NodeOperation {
{
m_use_conversion = use_conversion;
}
+ std::unique_ptr<MetaData> getMetaData() const override;
private:
bool m_use_conversion;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index eb20dfb69a2..dcdf2f48607 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -83,6 +83,7 @@
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_light.h"
#include "BKE_mask.h"
#include "BKE_material.h"
@@ -152,12 +153,14 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
IDNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{
+ BLI_assert(id->session_uuid != MAIN_ID_SESSION_UUID_UNSET);
+
IDNode *id_node = nullptr;
ID *id_cow = nullptr;
IDComponentsMask previously_visible_components_mask = 0;
uint32_t previous_eval_flags = 0;
DEGCustomDataMeshMasks previous_customdata_masks;
- IDInfo *id_info = id_info_hash_.lookup_default(id, nullptr);
+ IDInfo *id_info = id_info_hash_.lookup_default(id->session_uuid, nullptr);
if (id_info != nullptr) {
id_cow = id_info->id_cow;
previously_visible_components_mask = id_info->previously_visible_components_mask;
@@ -334,7 +337,8 @@ void DepsgraphNodeBuilder::begin_build()
id_info->previously_visible_components_mask = id_node->visible_components_mask;
id_info->previous_eval_flags = id_node->eval_flags;
id_info->previous_customdata_masks = id_node->customdata_masks;
- id_info_hash_.add_new(id_node->id_orig, id_info);
+ BLI_assert(!id_info_hash_.contains(id_node->id_orig_session_uuid));
+ id_info_hash_.add_new(id_node->id_orig_session_uuid, id_info);
id_node->id_cow = nullptr;
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 6f7a8b1c6b5..174f9b129f9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -285,8 +285,8 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder {
* very root is visible (aka not restricted.). */
bool is_parent_collection_visible_;
- /* Indexed by original ID, values are IDInfo. */
- Map<const ID *, IDInfo *> id_info_hash_;
+ /* Indexed by original ID.session_uuid, values are IDInfo. */
+ Map<uint, IDInfo *> id_info_hash_;
/* Set of IDs which were already build. Makes it easier to keep track of
* what was already built and what was not. */
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index 4f2fcab5823..8e159a7ff08 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -80,6 +80,7 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata))
/* Store ID-pointer. */
id_type = GS(id->name);
id_orig = (ID *)id;
+ id_orig_session_uuid = id->session_uuid;
eval_flags = 0;
previous_eval_flags = 0;
customdata_masks = DEGCustomDataMeshMasks();
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h
index 04a9006ac10..c4d36685bb8 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.h
+++ b/source/blender/depsgraph/intern/node/deg_node_id.h
@@ -74,12 +74,22 @@ struct IDNode : public Node {
IDComponentsMask get_visible_components_mask() const;
- /* ID Block referenced. */
/* Type of the ID stored separately, so it's possible to perform check whether CoW is needed
* without de-referencing the id_cow (which is not safe when ID is NOT covered by CoW and has
* been deleted from the main database.) */
ID_Type id_type;
+
+ /* ID Block referenced. */
ID *id_orig;
+
+ /* Session-wide UUID of the id_orig.
+ * Is used on relations update to map evaluated state from old nodes to the new ones, without
+ * relying on pointers (which are not guaranteed to be unique) and without dereferencing id_orig
+ * which could be "stale" pointer. */
+ uint id_orig_session_uuid;
+
+ /* Evaluated datablock.
+ * Will be covered by the copy-on-write system if the ID Type needs it. */
ID *id_cow;
/* Hash to make it faster to look up components. */
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 6cb829d3a23..05cbb3ef48f 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -892,7 +892,7 @@ static void acf_group_name(bAnimListElem *ale, char *name)
/* name property for group entries */
static bool acf_group_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
- RNA_pointer_create(ale->id, &RNA_ActionGroup, ale->data, ptr);
+ RNA_pointer_create(ale->fcurve_owner_id, &RNA_ActionGroup, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
@@ -1013,7 +1013,7 @@ static bool acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRN
* as our "name" so that user can perform quick fixes
*/
if (fcu->flag & FCURVE_DISABLED) {
- RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr);
+ RNA_pointer_create(ale->fcurve_owner_id, &RNA_FCurve, ale->data, ptr);
*prop = RNA_struct_find_property(ptr, "data_path");
}
else {
@@ -3965,7 +3965,7 @@ static void acf_nlaaction_name(bAnimListElem *ale, char *name)
static bool acf_nlaaction_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop)
{
if (ale->data) {
- RNA_pointer_create(ale->id, &RNA_Action, ale->data, ptr);
+ RNA_pointer_create(ale->fcurve_owner_id, &RNA_Action, ale->data, ptr);
*prop = RNA_struct_name_property(ptr->type);
return (*prop != NULL);
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 920f1d346b9..51be5afafe5 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -181,7 +181,7 @@ static void graph_panel_properties(const bContext *C, Panel *panel)
}
/* F-Curve pointer */
- RNA_pointer_create(ale->id, &RNA_FCurve, fcu, &fcu_ptr);
+ RNA_pointer_create(ale->fcurve_owner_id, &RNA_FCurve, fcu, &fcu_ptr);
/* user-friendly 'name' for F-Curve */
col = uiLayoutColumn(layout, false);
@@ -366,7 +366,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
int unit = B_UNIT_NONE;
/* RNA pointer to keyframe, to allow editing */
- RNA_pointer_create(ale->id, &RNA_Keyframe, bezt, &bezt_ptr);
+ RNA_pointer_create(ale->fcurve_owner_id, &RNA_Keyframe, bezt, &bezt_ptr);
/* get property that F-Curve affects, for some unit-conversion magic */
RNA_id_pointer_create(ale->id, &id_ptr);
diff --git a/source/blender/gpu/opengl/gl_backend.cc b/source/blender/gpu/opengl/gl_backend.cc
index 5c43a8990d7..29ff1b3e81a 100644
--- a/source/blender/gpu/opengl/gl_backend.cc
+++ b/source/blender/gpu/opengl/gl_backend.cc
@@ -159,11 +159,6 @@ void GLBackend::platform_init()
GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
}
}
- if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_OFFICIAL)) {
- if (is_faulty_T82856_platform(version, renderer)) {
- GPG.support_level = GPU_SUPPORT_LEVEL_LIMITED;
- }
- }
}
GPG.create_key(GPG.support_level, vendor, renderer, version);
GPG.create_gpu_name(vendor, renderer, version);
diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h
index 07c47965262..363ad45e0e6 100644
--- a/source/blender/imbuf/intern/IMB_indexer.h
+++ b/source/blender/imbuf/intern/IMB_indexer.h
@@ -48,9 +48,9 @@
typedef struct anim_index_entry {
int frameno;
- unsigned long long seek_pos;
- unsigned long long seek_pos_dts;
- unsigned long long pts;
+ uint64_t seek_pos;
+ uint64_t seek_pos_dts;
+ uint64_t pts;
} anim_index_entry;
struct anim_index {
@@ -77,28 +77,25 @@ typedef struct anim_index_builder {
} anim_index_builder;
anim_index_builder *IMB_index_builder_create(const char *name);
-void IMB_index_builder_add_entry(anim_index_builder *fp,
- int frameno,
- unsigned long long seek_pos,
- unsigned long long seek_pos_dts,
- unsigned long long pts);
+void IMB_index_builder_add_entry(
+ anim_index_builder *fp, int frameno, uint64_t seek_pos, uint64_t seek_pos_dts, uint64_t pts);
void IMB_index_builder_proc_frame(anim_index_builder *fp,
unsigned char *buffer,
int data_size,
int frameno,
- unsigned long long seek_pos,
- unsigned long long seek_pos_dts,
- unsigned long long pts);
+ uint64_t seek_pos,
+ uint64_t seek_pos_dts,
+ uint64_t pts);
void IMB_index_builder_finish(anim_index_builder *fp, int rollback);
struct anim_index *IMB_indexer_open(const char *name);
-unsigned long long IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index);
-unsigned long long IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index);
+uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index);
+uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index);
int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno);
-unsigned long long IMB_indexer_get_pts(struct anim_index *idx, int frame_index);
+uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index);
int IMB_indexer_get_duration(struct anim_index *idx);
int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index);
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index 9b01ea0840f..c40e65b1c5c 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -892,13 +892,12 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) {
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld "
- "%s\n",
+ "%sREAD: strID=%d (VID: %d) dts=%" PRId64 " pts=%" PRId64 " %s\n",
(anim->next_packet.stream_index == anim->videoStream) ? "->" : " ",
anim->next_packet.stream_index,
anim->videoStream,
- (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->next_packet.dts,
- (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->next_packet.pts,
+ (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet.dts,
+ (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->next_packet.pts,
(anim->next_packet.flags & AV_PKT_FLAG_KEY) ? " KEY" : "");
if (anim->next_packet.stream_index == anim->videoStream) {
anim->pFrameComplete = 0;
@@ -911,12 +910,10 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- " FRAME DONE: next_pts=%lld "
- "pkt_pts=%lld, guessed_pts=%lld\n",
- (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pts,
- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 :
- (long long int)anim->pFrame->pkt_pts,
- (long long int)anim->next_pts);
+ " FRAME DONE: next_pts=%" PRId64 " pkt_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
+ (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
+ (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pkt_pts,
+ (int64_t)anim->next_pts);
break;
}
}
@@ -946,11 +943,11 @@ static int ffmpeg_decode_video_frame(struct anim *anim)
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- " FRAME DONE (after EOF): next_pts=%lld "
- "pkt_pts=%lld, guessed_pts=%lld\n",
- (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pts,
- (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (long long int)anim->pFrame->pkt_pts,
- (long long int)anim->next_pts);
+ " FRAME DONE (after EOF): next_pts=%" PRId64 " pkt_pts=%" PRId64
+ ", guessed_pts=%" PRId64 "\n",
+ (anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pts,
+ (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ? -1 : (int64_t)anim->pFrame->pkt_pts,
+ (int64_t)anim->next_pts);
rval = 0;
}
}
@@ -975,16 +972,16 @@ static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_sea
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "SCAN start: considering pts=%lld in search of %lld\n",
- (long long int)anim->next_pts,
- (long long int)pts_to_search);
+ "SCAN start: considering pts=%" PRId64 " in search of %" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
while (count > 0 && anim->next_pts < pts_to_search) {
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- " WHILE: pts=%lld in search of %lld\n",
- (long long int)anim->next_pts,
- (long long int)pts_to_search);
+ " WHILE: pts=%" PRId64 " in search of %" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
if (!ffmpeg_decode_video_frame(anim)) {
break;
}
@@ -994,9 +991,9 @@ static void ffmpeg_decode_video_frame_scan(struct anim *anim, int64_t pts_to_sea
av_log(anim->pFormatCtx,
AV_LOG_ERROR,
"SCAN failed: completely lost in stream, "
- "bailing out at PTS=%lld, searching for PTS=%lld\n",
- (long long int)anim->next_pts,
- (long long int)pts_to_search);
+ "bailing out at PTS=%" PRId64 ", searching for PTS=%" PRId64 "\n",
+ (int64_t)anim->next_pts,
+ (int64_t)pts_to_search);
}
if (anim->next_pts == pts_to_search) {
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "SCAN HAPPY: we found our PTS!\n");
@@ -1091,9 +1088,9 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "FETCH: looking for PTS=%lld "
- "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n",
- (long long int)pts_to_search,
+ "FETCH: looking for PTS=%" PRId64 " (pts_timebase=%g, frame_rate=%g, st_time=%" PRId64
+ ")\n",
+ (int64_t)pts_to_search,
pts_time_base,
frame_rate,
st_time);
@@ -1101,9 +1098,9 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
if (anim->last_frame && anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search) {
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "FETCH: frame repeat: last: %lld next: %lld\n",
- (long long int)anim->last_pts,
- (long long int)anim->next_pts);
+ "FETCH: frame repeat: last: %" PRId64 " next: %" PRId64 "\n",
+ (int64_t)anim->last_pts,
+ (int64_t)anim->next_pts);
IMB_refImBuf(anim->last_frame);
anim->curposition = position;
return anim->last_frame;
@@ -1128,13 +1125,13 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
int ret;
if (tc_index) {
- unsigned long long dts;
+ uint64_t dts;
pos = IMB_indexer_get_seek_pos(tc_index, new_frame_index);
dts = IMB_indexer_get_seek_pos_dts(tc_index, new_frame_index);
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %lld\n", pos);
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %llu\n", dts);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek pos = %" PRId64 "\n", pos);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "TC INDEX seek dts = %" PRIu64 "\n", dts);
if (ffmpeg_seek_by_byte(anim->pFormatCtx)) {
av_log(anim->pFormatCtx, AV_LOG_DEBUG, "... using BYTE pos\n");
@@ -1152,7 +1149,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
av_log(anim->pFormatCtx,
AV_LOG_DEBUG,
- "NO INDEX seek pos = %lld, st_time = %lld\n",
+ "NO INDEX seek pos = %" PRId64 ", st_time = %" PRId64 "\n",
pos,
(st_time != AV_NOPTS_VALUE) ? st_time : 0);
@@ -1164,7 +1161,7 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
pos += st_time;
}
- av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %lld\n", pos);
+ av_log(anim->pFormatCtx, AV_LOG_DEBUG, "NO INDEX final seek pos = %" PRId64 "\n", pos);
ret = av_seek_frame(anim->pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
}
@@ -1173,11 +1170,11 @@ static ImBuf *ffmpeg_fetchibuf(struct anim *anim, int position, IMB_Timecode_Typ
av_log(anim->pFormatCtx,
AV_LOG_ERROR,
"FETCH: "
- "error while seeking to DTS = %lld "
- "(frameno = %d, PTS = %lld): errcode = %d\n",
+ "error while seeking to DTS = %" PRId64 " (frameno = %d, PTS = %" PRId64
+ "): errcode = %d\n",
pos,
position,
- (long long int)pts_to_search,
+ (int64_t)pts_to_search,
ret);
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 09f37d733de..20e1febedd7 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -99,25 +99,22 @@ anim_index_builder *IMB_index_builder_create(const char *name)
return rv;
}
-void IMB_index_builder_add_entry(anim_index_builder *fp,
- int frameno,
- unsigned long long seek_pos,
- unsigned long long seek_pos_dts,
- unsigned long long pts)
+void IMB_index_builder_add_entry(
+ anim_index_builder *fp, int frameno, uint64_t seek_pos, uint64_t seek_pos_dts, uint64_t pts)
{
fwrite(&frameno, sizeof(int), 1, fp->fp);
- fwrite(&seek_pos, sizeof(unsigned long long), 1, fp->fp);
- fwrite(&seek_pos_dts, sizeof(unsigned long long), 1, fp->fp);
- fwrite(&pts, sizeof(unsigned long long), 1, fp->fp);
+ fwrite(&seek_pos, sizeof(uint64_t), 1, fp->fp);
+ fwrite(&seek_pos_dts, sizeof(uint64_t), 1, fp->fp);
+ fwrite(&pts, sizeof(uint64_t), 1, fp->fp);
}
void IMB_index_builder_proc_frame(anim_index_builder *fp,
- unsigned char *buffer,
+ uchar *buffer,
int data_size,
int frameno,
- unsigned long long seek_pos,
- unsigned long long seek_pos_dts,
- unsigned long long pts)
+ uint64_t seek_pos,
+ uint64_t seek_pos_dts,
+ uint64_t pts)
{
if (fp->proc_frame) {
anim_index_entry e;
@@ -186,10 +183,10 @@ struct anim_index *IMB_indexer_open(const char *name)
fseek(fp, 0, SEEK_END);
- idx->num_entries = (ftell(fp) - 12) / (sizeof(int) + /* framepos */
- sizeof(unsigned long long) + /* seek_pos */
- sizeof(unsigned long long) + /* seek_pos_dts */
- sizeof(unsigned long long) /* pts */
+ idx->num_entries = (ftell(fp) - 12) / (sizeof(int) + /* framepos */
+ sizeof(uint64_t) + /* seek_pos */
+ sizeof(uint64_t) + /* seek_pos_dts */
+ sizeof(uint64_t) /* pts */
);
fseek(fp, 12, SEEK_SET);
@@ -197,28 +194,28 @@ struct anim_index *IMB_indexer_open(const char *name)
idx->entries = MEM_callocN(sizeof(struct anim_index_entry) * idx->num_entries,
"anim_index_entries");
+ size_t items_read = 0;
for (i = 0; i < idx->num_entries; i++) {
- size_t items_read = 0;
items_read += fread(&idx->entries[i].frameno, sizeof(int), 1, fp);
- items_read += fread(&idx->entries[i].seek_pos, sizeof(unsigned long long), 1, fp);
- items_read += fread(&idx->entries[i].seek_pos_dts, sizeof(unsigned long long), 1, fp);
- items_read += fread(&idx->entries[i].pts, sizeof(unsigned long long), 1, fp);
-
- if (items_read < 4) {
- perror("error reading animation index file");
- MEM_freeN(idx->entries);
- MEM_freeN(idx);
- fclose(fp);
- return NULL;
- }
+ items_read += fread(&idx->entries[i].seek_pos, sizeof(uint64_t), 1, fp);
+ items_read += fread(&idx->entries[i].seek_pos_dts, sizeof(uint64_t), 1, fp);
+ items_read += fread(&idx->entries[i].pts, sizeof(uint64_t), 1, fp);
+ }
+
+ if (UNLIKELY(items_read != idx->num_entries * 4)) {
+ perror("error reading animation index file");
+ MEM_freeN(idx->entries);
+ MEM_freeN(idx);
+ fclose(fp);
+ return NULL;
}
if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) {
for (i = 0; i < idx->num_entries; i++) {
BLI_endian_switch_int32(&idx->entries[i].frameno);
- BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos);
- BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts);
- BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts);
+ BLI_endian_switch_uint64(&idx->entries[i].seek_pos);
+ BLI_endian_switch_uint64(&idx->entries[i].seek_pos_dts);
+ BLI_endian_switch_uint64(&idx->entries[i].pts);
}
}
@@ -227,7 +224,7 @@ struct anim_index *IMB_indexer_open(const char *name)
return idx;
}
-unsigned long long IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index)
+uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index)
{
if (frame_index < 0) {
frame_index = 0;
@@ -238,7 +235,7 @@ unsigned long long IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_in
return idx->entries[frame_index].seek_pos;
}
-unsigned long long IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index)
+uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index)
{
if (frame_index < 0) {
frame_index = 0;
@@ -281,7 +278,7 @@ int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno)
return first;
}
-unsigned long long IMB_indexer_get_pts(struct anim_index *idx, int frame_index)
+uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index)
{
if (frame_index < 0) {
frame_index = 0;
@@ -707,12 +704,12 @@ typedef struct FFmpegIndexBuilderContext {
IMB_Timecode_Type tcs_in_use;
IMB_Proxy_Size proxy_sizes_in_use;
- unsigned long long seek_pos;
- unsigned long long last_seek_pos;
- unsigned long long seek_pos_dts;
- unsigned long long seek_pos_pts;
- unsigned long long last_seek_pos_dts;
- unsigned long long start_pts;
+ uint64_t seek_pos;
+ uint64_t last_seek_pos;
+ uint64_t seek_pos_dts;
+ uint64_t seek_pos_pts;
+ uint64_t last_seek_pos_dts;
+ uint64_t start_pts;
double frame_rate;
double pts_time_base;
int frameno, frameno_gapless;
@@ -847,9 +844,9 @@ static void index_rebuild_ffmpeg_proc_decoded_frame(FFmpegIndexBuilderContext *c
AVFrame *in_frame)
{
int i;
- unsigned long long s_pos = context->seek_pos;
- unsigned long long s_dts = context->seek_pos_dts;
- unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame);
+ uint64_t s_pos = context->seek_pos;
+ uint64_t s_dts = context->seek_pos_dts;
+ uint64_t pts = av_get_pts_from_frame(context->iFormatCtx, in_frame);
for (i = 0; i < context->num_proxy_sizes; i++) {
add_to_proxy_output_ffmpeg(context->proxy_ctx[i], in_frame);
diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc
index eace75b46b6..53af6073793 100644
--- a/source/blender/nodes/geometry/node_geometry_util.cc
+++ b/source/blender/nodes/geometry/node_geometry_util.cc
@@ -58,7 +58,7 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
return 4;
case CD_PROP_COLOR:
return 5;
-#if 0 /* Attribute types are not supported yet. */
+#if 0 /* These attribute types are not supported yet. */
case CD_MLOOPCOL:
return 3;
case CD_PROP_STRING:
@@ -71,7 +71,7 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
}
}
-CustomDataType attribute_domain_highest_complexity(Span<CustomDataType> data_types)
+CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType> data_types)
{
int highest_complexity = INT_MIN;
CustomDataType most_complex_type = CD_PROP_COLOR;
diff --git a/source/blender/nodes/geometry/node_geometry_util.hh b/source/blender/nodes/geometry/node_geometry_util.hh
index 12ede8b6ee0..b7b2afeefcb 100644
--- a/source/blender/nodes/geometry/node_geometry_util.hh
+++ b/source/blender/nodes/geometry/node_geometry_util.hh
@@ -44,7 +44,7 @@ void update_attribute_input_socket_availabilities(bNode &node,
const GeometryNodeAttributeInputMode mode,
const bool name_is_available = true);
-CustomDataType attribute_domain_highest_complexity(Span<CustomDataType>);
+CustomDataType attribute_data_type_highest_complexity(Span<CustomDataType>);
Array<uint32_t> get_geometry_element_ids_as_uints(const GeometryComponent &component,
const AttributeDomain domain);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
index 8a96a6ea866..7d49253c6a3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
@@ -37,12 +37,14 @@ static void execute_on_component(const GeoNodeExecParams &params, GeometryCompon
const bNode &bnode = params.node();
NodeAttributeColorRamp *node_storage = (NodeAttributeColorRamp *)bnode.storage;
+ /* Use the type of the input attribute, but create a color attribute if it doesn't exist yet. */
+ const CustomDataType result_type = params.get_input_attribute_data_type(
+ "Attribute", component, CD_PROP_COLOR);
+
const std::string result_name = params.get_input<std::string>("Result");
/* Once we support more domains at the user level, we have to decide how the result domain is
* chosen. */
const AttributeDomain result_domain = ATTR_DOMAIN_POINT;
- const CustomDataType result_type = CD_PROP_COLOR;
-
WriteAttributePtr attribute_result = component.attribute_try_ensure_for_write(
result_name, result_domain, result_type);
if (!attribute_result) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
index abfe3b43cb5..5d6e2412a3d 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
@@ -216,14 +216,12 @@ static CustomDataType get_data_type(GeometryComponent &component,
const NodeAttributeCompare &node_storage)
{
if (operation_tests_equality(node_storage)) {
- CustomDataType data_type_a = params.get_input_attribute_data_type(
- "A", component, CD_PROP_FLOAT);
- CustomDataType data_type_b = params.get_input_attribute_data_type(
- "B", component, CD_PROP_FLOAT);
-
/* Convert the input attributes to the same data type for the equality tests. Use the higher
* complexity attribute type, otherwise information necessary to the comparison may be lost. */
- return attribute_domain_highest_complexity({data_type_a, data_type_b});
+ return attribute_data_type_highest_complexity({
+ params.get_input_attribute_data_type("A", component, CD_PROP_FLOAT),
+ params.get_input_attribute_data_type("B", component, CD_PROP_FLOAT),
+ });
}
/* Use float compare for every operation besides equality. */
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 3d3a72dd910..9a780e1212b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
@@ -136,14 +136,21 @@ static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecPa
const bNode &node = params.node();
const NodeAttributeMix *node_storage = (const NodeAttributeMix *)node.storage;
- CustomDataType result_type = CD_PROP_COLOR;
+ /* Use the highest complexity data type among the inputs and outputs, that way the node will
+ * never "remove information". Use CD_PROP_BOOL as the lowest complexity data type, but in any
+ * real situation it won't be returned. */
+ const CustomDataType result_type = attribute_data_type_highest_complexity({
+ params.get_input_attribute_data_type("A", component, CD_PROP_BOOL),
+ params.get_input_attribute_data_type("B", component, CD_PROP_BOOL),
+ params.get_input_attribute_data_type("Result", component, CD_PROP_BOOL),
+ });
+
+ /* Once we support more domains at the user level, we have to decide how the result domain is
+ * chosen. */
AttributeDomain result_domain = ATTR_DOMAIN_POINT;
-
- /* Use type and domain from the result attribute, if it exists already. */
const std::string result_name = params.get_input<std::string>("Result");
const ReadAttributePtr result_attribute_read = component.attribute_try_get_for_read(result_name);
if (result_attribute_read) {
- result_type = result_attribute_read->custom_data_type();
result_domain = result_attribute_read->domain();
}
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index f33bb81d6b0..2ca21a315e4 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -228,13 +228,15 @@ add_blender_test(
--run-all-tests
)
-add_blender_test(
- physics_ocean
- ${TEST_SRC_DIR}/physics/ocean_test.blend
- --python ${TEST_PYTHON_DIR}/physics_ocean.py
- --
- --run-all-tests
-)
+if(WITH_MOD_OCEANSIM)
+ add_blender_test(
+ physics_ocean
+ ${TEST_SRC_DIR}/physics/ocean_test.blend
+ --python ${TEST_PYTHON_DIR}/physics_ocean.py
+ --
+ --run-all-tests
+ )
+endif()
add_blender_test(