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:
authorLukas Tönne <lukas.toenne@gmail.com>2016-12-01 12:29:46 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-12-01 12:29:46 +0300
commitff2a74906a7b70625a4e941c6a805f7734491204 (patch)
tree562f5ccdd9f4e377d20fe22eadca48201924b4b3
parent73c1c92c0e86ce1b5a8abeaa16be2bf2c259412b (diff)
parent58877d6d082d82185ca611b704364168e5984bd7 (diff)
Merge branch 'master' into blender2.8
-rwxr-xr-xbuild_files/build_environment/install_deps.sh27
-rw-r--r--build_files/cmake/platform/platform_win32_msvc.cmake2
-rw-r--r--extern/Eigen3/Eigen/src/StlSupport/StdVector.h4
-rw-r--r--extern/clew/include/clew.h3
-rw-r--r--extern/glog/src/raw_logging.cc3
-rw-r--r--extern/glog/src/stacktrace_powerpc-inl.h2
-rw-r--r--extern/rangetree/intern/range_tree.c2
-rw-r--r--intern/audaspace/FX/AUD_LimiterReader.cpp4
-rw-r--r--intern/cycles/blender/addon/properties.py55
-rw-r--r--intern/cycles/blender/addon/ui.py45
-rw-r--r--intern/cycles/blender/addon/version_update.py18
-rw-r--r--intern/cycles/blender/blender_object.cpp224
-rw-r--r--intern/cycles/blender/blender_session.cpp86
-rw-r--r--intern/cycles/blender/blender_session.h18
-rw-r--r--intern/cycles/blender/blender_sync.cpp14
-rw-r--r--intern/cycles/blender/blender_sync.h4
-rw-r--r--intern/cycles/device/device_cuda.cpp6
-rw-r--r--intern/cycles/device/opencl/opencl.h4
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp10
-rw-r--r--intern/cycles/kernel/kernel_volume.h22
-rw-r--r--intern/cycles/render/image.cpp112
-rw-r--r--intern/cycles/render/image.h53
-rw-r--r--intern/cycles/render/mesh.cpp4
-rw-r--r--intern/cycles/render/nodes.cpp2
-rw-r--r--intern/cycles/render/scene.cpp2
-rw-r--r--intern/cycles/render/scene.h5
-rw-r--r--intern/cycles/render/svm.cpp8
-rw-r--r--intern/cycles/util/CMakeLists.txt1
-rw-r--r--intern/cycles/util/util_image.h14
-rw-r--r--intern/cycles/util/util_image_impl.h168
-rw-r--r--intern/cycles/util/util_simd.h6
-rw-r--r--intern/cycles/util/util_system.cpp16
-rw-r--r--intern/cycles/util/util_system.h4
-rw-r--r--intern/cycles/util/util_task.cpp34
-rw-r--r--intern/cycles/util/util_windows.cpp15
-rw-r--r--intern/cycles/util/util_windows.h4
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp2
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp24
-rw-r--r--intern/opencolorio/fallback_impl.cc153
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py73
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py6
-rw-r--r--source/blender/alembic/intern/abc_camera.cc18
-rw-r--r--source/blender/alembic/intern/abc_curves.cc2
-rw-r--r--source/blender/alembic/intern/abc_curves.h2
-rw-r--r--source/blender/alembic/intern/abc_customdata.h5
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc14
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc286
-rw-r--r--source/blender/alembic/intern/abc_mesh.h15
-rw-r--r--source/blender/alembic/intern/abc_object.cc4
-rw-r--r--source/blender/alembic/intern/abc_object.h5
-rw-r--r--source/blender/alembic/intern/abc_points.cc7
-rw-r--r--source/blender/alembic/intern/abc_points.h2
-rw-r--r--source/blender/alembic/intern/abc_transform.cc3
-rw-r--r--source/blender/alembic/intern/abc_util.cc5
-rw-r--r--source/blender/alembic/intern/abc_util.h2
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc12
-rw-r--r--source/blender/blenkernel/BKE_animsys.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h1
-rw-r--r--source/blender/blenkernel/BKE_library.h1
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c8
-rw-r--r--source/blender/blenkernel/intern/brush.c3
-rw-r--r--source/blender/blenkernel/intern/camera.c4
-rw-r--r--source/blender/blenkernel/intern/constraint.c21
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c6
-rw-r--r--source/blender/blenkernel/intern/gpencil.c15
-rw-r--r--source/blender/blenkernel/intern/image.c1
-rw-r--r--source/blender/blenkernel/intern/library.c33
-rw-r--r--source/blender/blenkernel/intern/object.c8
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c3
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c4
-rw-r--r--source/blender/blenkernel/intern/sca.c22
-rw-r--r--source/blender/blenkernel/intern/scene.c8
-rw-r--r--source/blender/blenkernel/intern/sequencer.c3
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h1
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h3
-rw-r--r--source/blender/blenlib/intern/math_geom.c3
-rw-r--r--source/blender/blenlib/intern/math_matrix.c48
-rw-r--r--source/blender/blenlib/intern/math_rotation.c7
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/collada/ArmatureImporter.cpp1
-rw-r--r--source/blender/collada/collada_internal.cpp7
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc27
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc16
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c6
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c42
-rw-r--r--source/blender/editors/include/ED_gpencil.h2
-rw-r--r--source/blender/editors/include/UI_icons.h9
-rw-r--r--source/blender/editors/include/UI_interface.h2
-rw-r--r--source/blender/editors/interface/interface.c41
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c90
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/interface/interface_layout.c2
-rw-r--r--source/blender/editors/interface/interface_regions.c6
-rw-r--r--source/blender/editors/interface/interface_templates.c5
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c10
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/object/object_add.c153
-rw-r--r--source/blender/editors/object/object_relations.c98
-rw-r--r--source/blender/editors/object/object_warp.c3
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c7
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c15
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c5
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c15
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c2
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c5
-rw-r--r--source/blender/imbuf/intern/oiio/CMakeLists.txt5
-rw-r--r--source/blender/makesdna/DNA_ID.h6
-rw-r--r--source/blender/makesdna/DNA_node_types.h3
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h8
-rw-r--r--source/blender/makesrna/intern/makesrna.c6
-rw-r--r--source/blender/makesrna/intern/rna_ID.c10
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c10
-rw-r--r--source/blender/makesrna/intern/rna_main.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c12
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c22
-rw-r--r--source/blender/modifiers/intern/MOD_screw.c6
-rw-r--r--source/blender/python/mathutils/mathutils_bvhtree.c5
-rw-r--r--source/creator/CMakeLists.txt2
123 files changed, 1709 insertions, 827 deletions
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index 347a44d2900..8187971c6e7 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -705,6 +705,21 @@ if [ "$WITH_ALL" = true -a "$OPENCOLLADA_SKIP" = false ]; then
fi
+WARNING "****WARNING****"
+PRINT "If you are experiencing issues building Blender, _*TRY A FRESH, CLEAN BUILD FIRST*_!"
+PRINT "The same goes for install_deps itself, if you encounter issues, please first erase everything in $SRC and $INST"
+PRINT "(provided obviously you did not add anything yourself in those dirs!), and run install_deps.sh again!"
+PRINT "Often, changes in the libs built by this script, or in your distro package, cannot be handled simply, so..."
+PRINT ""
+PRINT "You may also try to use the '--build-foo' options to bypass your distribution's packages"
+PRINT "for some troublesome/buggy libraries..."
+PRINT ""
+PRINT ""
+PRINT "Ran with:"
+PRINT " install_deps.sh $COMMANDLINE"
+PRINT ""
+PRINT ""
+
# This has to be done here, because user might force some versions...
PYTHON_SOURCE=( "https://www.python.org/ftp/python/$PYTHON_VERSION/Python-$PYTHON_VERSION.tgz" )
@@ -777,6 +792,8 @@ However, if you are experiencing linking errors (also when building Blender itse
Please note that until the transition to C++11-built libraries if completed in your distribution, situation will
remain fuzzy and incompatibilities may happen..."
+ PRINT ""
+ PRINT ""
CXXFLAGS="$CXXFLAGS -std=c++11"
export CXXFLAGS
fi
@@ -4156,16 +4173,6 @@ print_info_ffmpeglink() {
print_info() {
PRINT ""
PRINT ""
- WARNING "****WARNING****"
- PRINT "If you are experiencing issues building Blender, _*TRY A FRESH, CLEAN BUILD FIRST*_!"
- PRINT "The same goes for install_deps itself, if you encounter issues, please first erase everything in $SRC and $INST"
- PRINT "(provided obviously you did not add anything yourself in those dirs!), and run install_deps.sh again!"
- PRINT "Often, changes in the libs built by this script, or in your distro package, cannot be handled simply, so..."
- PRINT ""
- PRINT "You may also try to use the '--build-foo' options to bypass your distribution's packages"
- PRINT "for some troublesome/buggy libraries..."
- PRINT ""
- PRINT ""
PRINT "Ran with:"
PRINT " install_deps.sh $COMMANDLINE"
PRINT ""
diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake
index 6ca0568b5fd..96c9ec91d11 100644
--- a/build_files/cmake/platform/platform_win32_msvc.cmake
+++ b/build_files/cmake/platform/platform_win32_msvc.cmake
@@ -112,7 +112,7 @@ set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
# MSVC only, Mingw doesnt need
if(CMAKE_CL_64)
- set(PLATFORM_LINKFLAGS "/MACHINE:X64 /OPT:NOREF ${PLATFORM_LINKFLAGS}")
+ set(PLATFORM_LINKFLAGS "/MACHINE:X64 ${PLATFORM_LINKFLAGS}")
else()
set(PLATFORM_LINKFLAGS "/MACHINE:IX86 /LARGEADDRESSAWARE ${PLATFORM_LINKFLAGS}")
endif()
diff --git a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
index 611664a2e8a..1894af6b779 100644
--- a/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
+++ b/extern/Eigen3/Eigen/src/StlSupport/StdVector.h
@@ -77,7 +77,7 @@ namespace std {
void resize(size_type new_size)
{ resize(new_size, T()); }
-#if defined(_VECTOR_)
+#if defined(_VECTOR_) && (_MSC_VER<1910)
// workaround MSVC std::vector implementation
void resize(size_type new_size, const value_type& x)
{
@@ -110,7 +110,7 @@ namespace std {
vector_base::insert(vector_base::end(), new_size - vector_base::size(), x);
}
#else
- // either GCC 4.1 or non-GCC
+ // either GCC 4.1, MSVC2017 or non-GCC
// default implementation which should always work.
void resize(size_type new_size, const value_type& x)
{
diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h
index 1f79c12481b..2a583c81599 100644
--- a/extern/clew/include/clew.h
+++ b/extern/clew/include/clew.h
@@ -369,7 +369,8 @@ typedef unsigned int cl_GLenum;
#endif
/* Define basic vector types */
-#if defined( __VEC__ )
+/* WOrkaround for ppc64el platform: conflicts with bool from C++. */
+#if defined( __VEC__ ) && !(defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
typedef vector unsigned char __cl_uchar16;
typedef vector signed char __cl_char16;
diff --git a/extern/glog/src/raw_logging.cc b/extern/glog/src/raw_logging.cc
index 7a7409bbf34..8517129fa81 100644
--- a/extern/glog/src/raw_logging.cc
+++ b/extern/glog/src/raw_logging.cc
@@ -59,7 +59,8 @@
# include <unistd.h>
#endif
-#if defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)
+// Hurd does not have SYS_write.
+#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && !defined(__GNU__)
# define safe_write(fd, s, len) syscall(SYS_write, fd, s, len)
#else
// Not so safe, but what can you do?
diff --git a/extern/glog/src/stacktrace_powerpc-inl.h b/extern/glog/src/stacktrace_powerpc-inl.h
index 1090ddedbc7..03b91089aad 100644
--- a/extern/glog/src/stacktrace_powerpc-inl.h
+++ b/extern/glog/src/stacktrace_powerpc-inl.h
@@ -111,7 +111,7 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
result[n++] = *(sp+2);
#elif defined(_CALL_SYSV)
result[n++] = *(sp+1);
-#elif defined(__APPLE__) || (defined(__linux) && defined(__PPC64__))
+#elif defined(__APPLE__) || ((defined(__linux) || defined(__linux__)) && defined(__PPC64__))
// This check is in case the compiler doesn't define _CALL_AIX/etc.
result[n++] = *(sp+2);
#elif defined(__linux)
diff --git a/extern/rangetree/intern/range_tree.c b/extern/rangetree/intern/range_tree.c
index 4c81036dceb..77496e32fa3 100644
--- a/extern/rangetree/intern/range_tree.c
+++ b/extern/rangetree/intern/range_tree.c
@@ -808,7 +808,7 @@ bool range_tree_uint_retake(RangeTreeUInt *rt, const uint value)
uint range_tree_uint_take_any(RangeTreeUInt *rt)
{
- Node *node = node = rt->list.first;
+ Node *node = rt->list.first;
uint value = node->min;
if (value == node->max) {
rt_node_remove(rt, node);
diff --git a/intern/audaspace/FX/AUD_LimiterReader.cpp b/intern/audaspace/FX/AUD_LimiterReader.cpp
index 9c1d4443b06..7d850ac7b5f 100644
--- a/intern/audaspace/FX/AUD_LimiterReader.cpp
+++ b/intern/audaspace/FX/AUD_LimiterReader.cpp
@@ -110,10 +110,10 @@ void AUD_LimiterReader::read(int& length, bool& eos, sample_t* buffer)
eos = true;
}
- if(position < m_start * rate)
+ if(position < int(m_start * rate))
{
int len2 = length;
- for(int len = m_start * rate - position;
+ for(int len = int(m_start * rate) - position;
len2 == length && !eos;
len -= length)
{
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index fc08a913f58..3346beea3b2 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -30,7 +30,7 @@ import _cycles
enum_devices = (
('CPU', "CPU", "Use CPU for rendering"),
- ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in user preferences"),
+ ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in the system tab in the user preferences"),
)
if _cycles.with_network:
@@ -129,6 +129,16 @@ enum_device_type = (
('OPENCL', "OpenCL", "OpenCL", 2)
)
+enum_texture_limit = (
+ ('OFF', "No Limit", "No texture size limit", 0),
+ ('128', "128", "Limit texture size to 128 pixels", 1),
+ ('256', "256", "Limit texture size to 256 pixels", 2),
+ ('512', "512", "Limit texture size to 512 pixels", 3),
+ ('1024', "1024", "Limit texture size to 1024 pixels", 4),
+ ('2048', "2048", "Limit texture size to 2048 pixels", 5),
+ ('4096', "4096", "Limit texture size to 4096 pixels", 6),
+ ('8192', "8192", "Limit texture size to 8192 pixels", 7),
+ )
class CyclesRenderSettings(bpy.types.PropertyGroup):
@classmethod
@@ -566,6 +576,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
min=0.0, max=5.0
)
+ cls.use_distance_cull = BoolProperty(
+ name="Use Distance Cull",
+ description="Allow objects to be culled based on the distance from camera",
+ default=False,
+ )
+
+ cls.distance_cull_margin = FloatProperty(
+ name="Cull Distance",
+ description="Cull objects which are further away from camera than this distance",
+ default=50,
+ min=0.0
+ )
+
cls.motion_blur_position = EnumProperty(
name="Motion Blur Position",
default='CENTER',
@@ -595,6 +618,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
min=0.0, max=1.0,
)
+ cls.texture_limit = EnumProperty(
+ name="Viewport Texture Limit",
+ default='OFF',
+ description="Limit texture size used by viewport rendering",
+ items=enum_texture_limit
+ )
+
+ cls.texture_limit_render = EnumProperty(
+ name="Render Texture Limit",
+ default='OFF',
+ description="Limit texture size used by final rendering",
+ items=enum_texture_limit
+ )
+
# Various fine-tuning debug flags
def devices_update_callback(self, context):
@@ -1016,6 +1053,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
default=False,
)
+ cls.use_distance_cull = BoolProperty(
+ name="Use Distance Cull",
+ description="Allow this object and its duplicators to be culled by distance from camera",
+ default=False,
+ )
+
cls.use_adaptive_subdivision = BoolProperty(
name="Use Adaptive Subdivision",
description="Use adaptive render time subdivision",
@@ -1126,7 +1169,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
def get_devices(self):
import _cycles
- # Layout of the device tuples: (Name, Type, Internal ID, Persistent ID)
+ # Layout of the device tuples: (Name, Type, Persistent ID)
device_list = _cycles.available_devices()
cuda_devices = []
@@ -1174,21 +1217,19 @@ class CyclesPreferences(bpy.types.AddonPreferences):
def draw_impl(self, layout, context):
- layout.label(text="Compute Device:")
+ layout.label(text="Cycles Compute Device:")
layout.row().prop(self, "compute_device_type", expand=True)
cuda_devices, opencl_devices = self.get_devices()
row = layout.row()
- if cuda_devices:
+ if self.compute_device_type == 'CUDA' and cuda_devices:
col = row.column(align=True)
- col.label(text="CUDA devices:")
for device in cuda_devices:
col.prop(device, "use", text=device.name, toggle=True)
- if opencl_devices:
+ if self.compute_device_type == 'OPENCL' and opencl_devices:
col = row.column(align=True)
- col.label(text="OpenCL devices:")
for device in opencl_devices:
col.prop(device, "use", text=device.name, toggle=True)
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7ed8c5f0a13..95731562c79 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -769,6 +769,8 @@ class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
row = col.row()
row.active = scene.render.use_simplify and cscene.use_camera_cull
row.prop(cob, "use_camera_cull")
+ row.active = scene.render.use_simplify and cscene.use_distance_cull
+ row.prop(cob, "use_distance_cull")
class CYCLES_OT_use_shading_nodes(Operator):
@@ -1523,22 +1525,35 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
cscene = scene.cycles
layout.active = rd.use_simplify
- split = layout.split()
- col = split.column()
- col.label(text="Viewport:")
- col.prop(rd, "simplify_subdivision", text="Subdivision")
+ col = layout.column(align=True)
+ col.label(text="Subdivision")
+ row = col.row(align=True)
+ row.prop(rd, "simplify_subdivision", text="Viewport")
+ row.prop(rd, "simplify_subdivision_render", text="Render")
- col = split.column()
- col.label(text="Render:")
- col.prop(rd, "simplify_subdivision_render", text="Subdivision")
- col = layout.column()
+ col = layout.column(align=True)
+ split = col.split()
+ sub = split.column()
+ sub.label(text="Texture Limit Viewport")
+ sub.prop(cscene, "texture_limit", text="")
+ sub = split.column()
+ sub.label(text="Texture Limit Render")
+ sub.prop(cscene, "texture_limit_render", text="")
+
+ split = layout.split()
+ col = split.column()
col.prop(cscene, "use_camera_cull")
- subsub = col.column()
- subsub.active = cscene.use_camera_cull
- subsub.prop(cscene, "camera_cull_margin")
+ row = col.row()
+ row.active = cscene.use_camera_cull
+ row.prop(cscene, "camera_cull_margin")
+ col = split.column()
+ col.prop(cscene, "use_distance_cull")
+ row = col.row()
+ row.active = cscene.use_distance_cull
+ row.prop(cscene, "distance_cull_margin", text="Distance")
def draw_device(self, context):
scene = context.scene
@@ -1552,11 +1567,9 @@ def draw_device(self, context):
split = layout.split(percentage=1/3)
split.label("Device:")
- row = split.row(align=True)
- sub = row.split(align=True)
- sub.active = show_device_selection(context)
- sub.prop(cscene, "device", text="")
- row.operator("wm.addon_userpref_show", text="", icon='PREFERENCES').module = __package__
+ row = split.row()
+ row.active = show_device_selection(context)
+ row.prop(cscene, "device", text="")
if engine.with_osl() and use_cpu(context):
layout.prop(cscene, "shading_system")
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index 951afd37a92..b2a745500a1 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -172,6 +172,24 @@ def custom_bake_remap(scene):
@persistent
def do_versions(self):
+ if bpy.context.user_preferences.version <= (2, 78, 1):
+ prop = bpy.context.user_preferences.addons[__package__].preferences
+ system = bpy.context.user_preferences.system
+ if not prop.is_property_set("compute_device_type"):
+ # Device might not currently be available so this can fail
+ try:
+ if system.legacy_compute_device_type == 1:
+ prop.compute_device_type = 'OPENCL'
+ elif system.legacy_compute_device_type == 2:
+ prop.compute_device_type = 'CUDA'
+ else:
+ prop.compute_device_type = 'NONE'
+ except:
+ pass
+
+ # Init device list for UI
+ prop.get_devices()
+
# We don't modify startup file because it assumes to
# have all the default values only.
if not bpy.data.is_saved:
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 16e32cb47e0..0d1b2fc4737 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -88,6 +88,143 @@ static uint object_ray_visibility(BL::Object& b_ob)
return flag;
}
+/* Culling */
+
+class BlenderObjectCulling
+{
+public:
+ BlenderObjectCulling(Scene *scene, BL::Scene& b_scene)
+ : use_scene_camera_cull(false),
+ use_camera_cull(false),
+ camera_cull_margin(0.0f),
+ use_scene_distance_cull(false),
+ use_distance_cull(false),
+ distance_cull_margin(0.0f)
+ {
+ if(b_scene.render().use_simplify()) {
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+
+ use_scene_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_camera_cull");
+ use_scene_distance_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_distance_cull");
+
+ camera_cull_margin = get_float(cscene, "camera_cull_margin");
+ distance_cull_margin = get_float(cscene, "distance_cull_margin");
+
+ if (distance_cull_margin == 0.0f) {
+ use_scene_distance_cull = false;
+ }
+ }
+ }
+
+ void init_object(Scene *scene, BL::Object& b_ob)
+ {
+ if(!use_scene_camera_cull && !use_scene_distance_cull) {
+ return;
+ }
+
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+
+ use_camera_cull = use_scene_camera_cull && get_boolean(cobject, "use_camera_cull");
+ use_distance_cull = use_scene_distance_cull && get_boolean(cobject, "use_distance_cull");
+
+ if(use_camera_cull || use_distance_cull) {
+ /* Need to have proper projection matrix. */
+ scene->camera->update();
+ }
+ }
+
+ bool test(Scene *scene, BL::Object& b_ob, Transform& tfm)
+ {
+ if(!use_camera_cull && !use_distance_cull) {
+ return false;
+ }
+
+ /* Compute world space bounding box corners. */
+ float3 bb[8];
+ BL::Array<float, 24> boundbox = b_ob.bound_box();
+ for(int i = 0; i < 8; ++i) {
+ float3 p = make_float3(boundbox[3 * i + 0],
+ boundbox[3 * i + 1],
+ boundbox[3 * i + 2]);
+ bb[i] = transform_point(&tfm, p);
+ }
+
+ bool camera_culled = use_camera_cull && test_camera(scene, bb);
+ bool distance_culled = use_distance_cull && test_distance(scene, bb);
+
+ return ((camera_culled && distance_culled) ||
+ (camera_culled && !use_distance_cull) ||
+ (distance_culled && !use_camera_cull));
+ }
+
+private:
+ /* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
+ * to reduce number of objects which are wrongly considered visible.
+ */
+ bool test_camera(Scene *scene, float3 bb[8])
+ {
+ Camera *cam = scene->camera;
+ Transform& worldtondc = cam->worldtondc;
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ bool all_behind = true;
+ for(int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ float4 b = make_float4(p.x, p.y, p.z, 1.0f);
+ float4 c = make_float4(dot(worldtondc.x, b),
+ dot(worldtondc.y, b),
+ dot(worldtondc.z, b),
+ dot(worldtondc.w, b));
+ p = float4_to_float3(c / c.w);
+ if(c.z < 0.0f) {
+ p.x = 1.0f - p.x;
+ p.y = 1.0f - p.y;
+ }
+ if(c.z >= -camera_cull_margin) {
+ all_behind = false;
+ }
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+ if(all_behind) {
+ return true;
+ }
+ return (bb_min.x >= 1.0f + camera_cull_margin ||
+ bb_min.y >= 1.0f + camera_cull_margin ||
+ bb_max.x <= -camera_cull_margin ||
+ bb_max.y <= -camera_cull_margin);
+ }
+
+ bool test_distance(Scene *scene, float3 bb[8])
+ {
+ float3 camera_position = transform_get_column(&scene->camera->matrix, 3);
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+
+ /* Find min & max points for x & y & z on bounding box */
+ for(int i = 0; i < 8; ++i) {
+ float3 p = bb[i];
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+
+ float3 closest_point = max(min(bb_max,camera_position),bb_min);
+ return (len_squared(camera_position - closest_point) >
+ distance_cull_margin * distance_cull_margin);
+ }
+
+ bool use_scene_camera_cull;
+ bool use_camera_cull;
+ float camera_cull_margin;
+ bool use_scene_distance_cull;
+ bool use_distance_cull;
+ float distance_cull_margin;
+};
+
/* Light */
void BlenderSync::sync_light(BL::Object& b_parent,
@@ -235,55 +372,6 @@ void BlenderSync::sync_background_light(bool use_portal)
/* Object */
-/* TODO(sergey): Not really optimal, consider approaches based on k-DOP in order
- * to reduce number of objects which are wrongly considered visible.
- */
-static bool object_boundbox_clip(Scene *scene,
- BL::Object& b_ob,
- Transform& tfm,
- float margin)
-{
- Camera *cam = scene->camera;
- Transform& worldtondc = cam->worldtondc;
- BL::Array<float, 24> boundbox = b_ob.bound_box();
- float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
- bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
- bool all_behind = true;
- for(int i = 0; i < 8; ++i) {
- float3 p = make_float3(boundbox[3 * i + 0],
- boundbox[3 * i + 1],
- boundbox[3 * i + 2]);
- p = transform_point(&tfm, p);
-
- float4 b = make_float4(p.x, p.y, p.z, 1.0f);
- float4 c = make_float4(dot(worldtondc.x, b),
- dot(worldtondc.y, b),
- dot(worldtondc.z, b),
- dot(worldtondc.w, b));
- p = float4_to_float3(c / c.w);
- if(c.z < 0.0f) {
- p.x = 1.0f - p.x;
- p.y = 1.0f - p.y;
- }
- if(c.z >= -margin) {
- all_behind = false;
- }
- bb_min = min(bb_min, p);
- bb_max = max(bb_max, p);
- }
- if(!all_behind) {
- if(bb_min.x >= 1.0f + margin ||
- bb_min.y >= 1.0f + margin ||
- bb_max.x <= -margin ||
- bb_max.y <= -margin)
- {
- return true;
- }
- return false;
- }
- return true;
-}
-
Object *BlenderSync::sync_object(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
BL::DupliObject& b_dupli_ob,
@@ -291,8 +379,7 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
uint layer_flag,
float motion_time,
bool hide_tris,
- bool use_camera_cull,
- float camera_cull_margin,
+ BlenderObjectCulling& culling,
bool *use_portal)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
@@ -308,11 +395,12 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
}
/* only interested in object that we can create meshes from */
- if(!object_is_mesh(b_ob))
+ if(!object_is_mesh(b_ob)) {
return NULL;
+ }
- /* Perform camera space culling. */
- if(use_camera_cull && object_boundbox_clip(scene, b_ob, tfm, camera_cull_margin)) {
+ /* Perform object culling. */
+ if(culling.test(scene, b_ob, tfm)) {
return NULL;
}
@@ -519,17 +607,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
mesh_motion_synced.clear();
}
- bool allow_camera_cull = false;
- float camera_cull_margin = 0.0f;
- if(b_scene.render().use_simplify()) {
- PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
- allow_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
- !b_scene.render().use_multiview() &&
- get_boolean(cscene, "use_camera_cull");
- if(allow_camera_cull) {
- camera_cull_margin = get_float(cscene, "camera_cull_margin");
- }
- }
+ /* initialize culling */
+ BlenderObjectCulling culling(scene, b_scene);
/* object loop */
BL::Scene::object_bases_iterator b_base;
@@ -561,12 +640,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
if(!hide) {
progress.set_sync_status("Synchronizing object", b_ob.name());
- PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
- bool use_camera_cull = allow_camera_cull && get_boolean(cobject, "use_camera_cull");
- if(use_camera_cull) {
- /* Need to have proper projection matrix. */
- scene->camera->update();
- }
+ /* load per-object culling data */
+ culling.init_object(scene, b_ob);
+
if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) {
/* dupli objects */
b_ob.dupli_list_create(b_scene, dupli_settings);
@@ -593,8 +669,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
ob_layer,
motion_time,
hide_tris,
- use_camera_cull,
- camera_cull_margin,
+ culling,
&use_portal);
}
}
@@ -616,8 +691,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D& b_v3d, float motion_time)
ob_layer,
motion_time,
hide_tris,
- use_camera_cull,
- camera_cull_margin,
+ culling,
&use_portal);
}
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 171153dd440..e16cea0ebaf 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -126,8 +126,8 @@ void BlenderSession::create_session()
/* setup callbacks for builtin image support */
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7);
- scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3);
- scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3);
+ scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4);
+ scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4);
/* create session */
session = new Session(session_params);
@@ -1080,7 +1080,13 @@ int BlenderSession::builtin_image_frame(const string &builtin_name)
return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
}
-void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels)
+void BlenderSession::builtin_image_info(const string &builtin_name,
+ void *builtin_data,
+ bool &is_float,
+ int &width,
+ int &height,
+ int &depth,
+ int &channels)
{
/* empty image */
is_float = false;
@@ -1158,60 +1164,67 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti
}
}
-bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels)
+bool BlenderSession::builtin_image_pixels(const string &builtin_name,
+ void *builtin_data,
+ unsigned char *pixels,
+ const size_t pixels_size)
{
- if(!builtin_data)
+ if(!builtin_data) {
return false;
+ }
- int frame = builtin_image_frame(builtin_name);
+ const int frame = builtin_image_frame(builtin_name);
PointerRNA ptr;
RNA_id_pointer_create((ID*)builtin_data, &ptr);
BL::Image b_image(ptr);
- int width = b_image.size()[0];
- int height = b_image.size()[1];
- int channels = b_image.channels();
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
- unsigned char *image_pixels;
- image_pixels = image_get_pixels_for_frame(b_image, frame);
- size_t num_pixels = ((size_t)width) * height;
+ unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame);
+ const size_t num_pixels = ((size_t)width) * height;
- if(image_pixels) {
- memcpy(pixels, image_pixels, num_pixels * channels * sizeof(unsigned char));
+ if(image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(unsigned char));
MEM_freeN(image_pixels);
}
else {
if(channels == 1) {
- memset(pixels, 0, num_pixels * sizeof(unsigned char));
+ memset(pixels, 0, pixels_size * sizeof(unsigned char));
}
else {
+ const size_t num_pixels_safe = pixels_size / channels;
unsigned char *cp = pixels;
- for(size_t i = 0; i < num_pixels; i++, cp += channels) {
+ for(size_t i = 0; i < num_pixels_safe; i++, cp += channels) {
cp[0] = 255;
cp[1] = 0;
cp[2] = 255;
- if(channels == 4)
+ if(channels == 4) {
cp[3] = 255;
+ }
}
}
}
-
- /* premultiply, byte images are always straight for blender */
+ /* Premultiply, byte images are always straight for Blender. */
unsigned char *cp = pixels;
for(size_t i = 0; i < num_pixels; i++, cp += channels) {
cp[0] = (cp[0] * cp[3]) >> 8;
cp[1] = (cp[1] * cp[3]) >> 8;
cp[2] = (cp[2] * cp[3]) >> 8;
}
-
return true;
}
-bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels)
+bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
+ void *builtin_data,
+ float *pixels,
+ const size_t pixels_size)
{
- if(!builtin_data)
+ if(!builtin_data) {
return false;
+ }
PointerRNA ptr;
RNA_id_pointer_create((ID*)builtin_data, &ptr);
@@ -1222,16 +1235,16 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
BL::Image b_image(b_id);
int frame = builtin_image_frame(builtin_name);
- int width = b_image.size()[0];
- int height = b_image.size()[1];
- int channels = b_image.channels();
+ const int width = b_image.size()[0];
+ const int height = b_image.size()[1];
+ const int channels = b_image.channels();
float *image_pixels;
image_pixels = image_get_float_pixels_for_frame(b_image, frame);
- size_t num_pixels = ((size_t)width) * height;
+ const size_t num_pixels = ((size_t)width) * height;
- if(image_pixels) {
- memcpy(pixels, image_pixels, num_pixels * channels * sizeof(float));
+ if(image_pixels && num_pixels * channels == pixels_size) {
+ memcpy(pixels, image_pixels, pixels_size * sizeof(float));
MEM_freeN(image_pixels);
}
else {
@@ -1239,13 +1252,15 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
memset(pixels, 0, num_pixels * sizeof(float));
}
else {
+ const size_t num_pixels_safe = pixels_size / channels;
float *fp = pixels;
- for(int i = 0; i < num_pixels; i++, fp += channels) {
+ for(int i = 0; i < num_pixels_safe; i++, fp += channels) {
fp[0] = 1.0f;
fp[1] = 0.0f;
fp[2] = 1.0f;
- if(channels == 4)
+ if(channels == 4) {
fp[3] = 1.0f;
+ }
}
}
}
@@ -1257,8 +1272,9 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
BL::Object b_ob(b_id);
BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
- if(!b_domain)
+ if(!b_domain) {
return false;
+ }
int3 resolution = get_int3(b_domain.domain_resolution());
int length, amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1;
@@ -1270,10 +1286,10 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
amplify = 1;
}
- int width = resolution.x * amplify;
- int height = resolution.y * amplify;
- int depth = resolution.z * amplify;
- size_t num_pixels = ((size_t)width) * height * depth;
+ const int width = resolution.x * amplify;
+ const int height = resolution.y * amplify;
+ const int depth = resolution.z * amplify;
+ const size_t num_pixels = ((size_t)width) * height * depth;
if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 66a6945cbc1..82fe218b4ce 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -145,9 +145,21 @@ protected:
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
int builtin_image_frame(const string &builtin_name);
- void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels);
- bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels);
- bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels);
+ void builtin_image_info(const string &builtin_name,
+ void *builtin_data,
+ bool &is_float,
+ int &width,
+ int &height,
+ int &depth,
+ int &channels);
+ bool builtin_image_pixels(const string &builtin_name,
+ void *builtin_data,
+ unsigned char *pixels,
+ const size_t pixels_size);
+ bool builtin_image_float_pixels(const string &builtin_name,
+ void *builtin_data,
+ float *pixels,
+ const size_t pixels_size);
/* Update tile manager to reflect resumable render settings. */
void update_resumable_tile_manager(int num_samples);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 49ddc8af9a8..cfb32651c50 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -496,6 +496,20 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
else
params.persistent_data = false;
+ int texture_limit;
+ if(background) {
+ texture_limit = RNA_enum_get(&cscene, "texture_limit_render");
+ }
+ else {
+ texture_limit = RNA_enum_get(&cscene, "texture_limit");
+ }
+ if(texture_limit > 0 && b_scene.render().use_simplify()) {
+ params.texture_limit = 1 << (texture_limit + 6);
+ }
+ else {
+ params.texture_limit = 0;
+ }
+
#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
if(is_cpu) {
params.use_qbvh = DebugFlags().cpu.qbvh && system_cpu_support_sse2();
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 2fad7d5fe71..08e0a9bd82f 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -35,6 +35,7 @@
CCL_NAMESPACE_BEGIN
class Background;
+class BlenderObjectCulling;
class Camera;
class Film;
class Light;
@@ -122,8 +123,7 @@ private:
uint layer_flag,
float motion_time,
bool hide_tris,
- bool use_camera_cull,
- float camera_cull_margin,
+ BlenderObjectCulling& culling,
bool *use_portal);
void sync_light(BL::Object& b_parent,
int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index a4818aa3b8d..fbb97f78e70 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -1418,7 +1418,11 @@ void device_cuda_info(vector<DeviceInfo>& devices)
cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
cuDeviceGetAttribute(&pci_location[1], CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, num);
cuDeviceGetAttribute(&pci_location[2], CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, num);
- info.id = string_printf("CUDA_%s_%04x:%02x:%02x", name, pci_location[0], pci_location[1], pci_location[2]);
+ info.id = string_printf("CUDA_%s_%04x:%02x:%02x",
+ name,
+ (unsigned int)pci_location[0],
+ (unsigned int)pci_location[1],
+ (unsigned int)pci_location[2]);
/* if device has a kernel timeout, assume it is used for display */
if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h
index 054ac9014f0..4023ba89a10 100644
--- a/intern/cycles/device/opencl/opencl.h
+++ b/intern/cycles/device/opencl/opencl.h
@@ -16,14 +16,14 @@
#ifdef WITH_OPENCL
-#include "clew.h"
-
#include "device.h"
#include "util_map.h"
#include "util_param.h"
#include "util_string.h"
+#include "clew.h"
+
CCL_NAMESPACE_BEGIN
#define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index 36eb70b8c85..82e1640e508 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -667,7 +667,10 @@ string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
/* Use cl_amd_device_topology extension. */
cl_char topology[24];
if(clGetDeviceInfo(device_id, 0x4037, sizeof(topology), topology, NULL) == CL_SUCCESS && topology[0] == 1) {
- return string_printf("%02x:%02x.%01x", topology[21], topology[22], topology[23]);
+ return string_printf("%02x:%02x.%01x",
+ (unsigned int)topology[21],
+ (unsigned int)topology[22],
+ (unsigned int)topology[23]);
}
}
else if(platform_name == "NVIDIA CUDA") {
@@ -675,7 +678,10 @@ string OpenCLInfo::get_hardware_id(string platform_name, cl_device_id device_id)
cl_int bus_id, slot_id;
if(clGetDeviceInfo(device_id, 0x4008, sizeof(cl_int), &bus_id, NULL) == CL_SUCCESS &&
clGetDeviceInfo(device_id, 0x4009, sizeof(cl_int), &slot_id, NULL) == CL_SUCCESS) {
- return string_printf("%02x:%02x.%01x", bus_id, slot_id>>3, slot_id & 0x7);
+ return string_printf("%02x:%02x.%01x",
+ (unsigned int)(bus_id),
+ (unsigned int)(slot_id >> 3),
+ (unsigned int)(slot_id & 0x7));
}
}
/* No general way to get a hardware ID from OpenCL => give up. */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 0f45b0e7d60..dd7b0d9812d 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -245,11 +245,18 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, floa
float t = ray->t;
float delta = dot((light_P - ray->P) , ray->D);
- float D = sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ if(UNLIKELY(D == 0.0f)) {
+ *pdf = 0.0f;
+ return 0.0f;
+ }
float theta_a = -atan2f(delta, D);
float theta_b = atan2f(t - delta, D);
float t_ = D * tanf((xi * theta_b) + (1 - xi) * theta_a);
-
+ if(UNLIKELY(theta_b == theta_a)) {
+ *pdf = 0.0f;
+ return 0.0f;
+ }
*pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
return min(t, delta + t_); /* min is only for float precision errors */
@@ -258,13 +265,19 @@ ccl_device float kernel_volume_equiangular_sample(Ray *ray, float3 light_P, floa
ccl_device float kernel_volume_equiangular_pdf(Ray *ray, float3 light_P, float sample_t)
{
float delta = dot((light_P - ray->P) , ray->D);
- float D = sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ float D = safe_sqrtf(len_squared(light_P - ray->P) - delta * delta);
+ if(UNLIKELY(D == 0.0f)) {
+ return 0.0f;
+ }
float t = ray->t;
float t_ = sample_t - delta;
float theta_a = -atan2f(delta, D);
float theta_b = atan2f(t - delta, D);
+ if(UNLIKELY(theta_b == theta_a)) {
+ return 0.0f;
+ }
float pdf = D / ((theta_b - theta_a) * (D * D + t_ * t_));
@@ -958,6 +971,9 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
mis_weight = 2.0f*power_heuristic(pdf, distance_pdf);
}
}
+ if(sample_t < 1e-6f) {
+ return VOLUME_PATH_SCATTERED;
+ }
/* compute transmittance up to this step */
if(step != segment->steps)
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 7465fbd43a7..ab830b19c57 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -19,6 +19,7 @@
#include "scene.h"
#include "util_foreach.h"
+#include "util_logging.h"
#include "util_path.h"
#include "util_progress.h"
#include "util_texture.h"
@@ -476,6 +477,7 @@ template<TypeDesc::BASETYPE FileFormat,
typename DeviceType>
bool ImageManager::file_load_image(Image *img,
ImageDataType type,
+ int texture_limit,
device_vector<DeviceType>& tex_img)
{
const StorageType alpha_one = (FileFormat == TypeDesc::UINT8)? 255 : 1;
@@ -485,11 +487,18 @@ bool ImageManager::file_load_image(Image *img,
return false;
}
/* Read RGBA pixels. */
- StorageType *pixels = (StorageType*)tex_img.resize(width, height, depth);
- if(pixels == NULL) {
- return false;
+ vector<StorageType> pixels_storage;
+ StorageType *pixels;
+ const size_t max_size = max(max(width, height), depth);
+ if(texture_limit > 0 && max_size > texture_limit) {
+ pixels_storage.resize(((size_t)width)*height*depth*4);
+ pixels = &pixels_storage[0];
+ }
+ else {
+ pixels = (StorageType*)tex_img.resize(width, height, depth);
}
bool cmyk = false;
+ const size_t num_pixels = ((size_t)width) * height * depth;
if(in) {
StorageType *readpixels = pixels;
vector<StorageType> tmppixels;
@@ -526,12 +535,14 @@ bool ImageManager::file_load_image(Image *img,
if(FileFormat == TypeDesc::FLOAT) {
builtin_image_float_pixels_cb(img->filename,
img->builtin_data,
- (float*)pixels);
+ (float*)&pixels[0],
+ num_pixels * components);
}
else if(FileFormat == TypeDesc::UINT8) {
builtin_image_pixels_cb(img->filename,
img->builtin_data,
- (uchar*)pixels);
+ (uchar*)&pixels[0],
+ num_pixels * components);
}
else {
/* TODO(dingto): Support half for ImBuf. */
@@ -540,11 +551,10 @@ bool ImageManager::file_load_image(Image *img,
/* Check if we actually have a float4 slot, in case components == 1,
* but device doesn't support single channel textures.
*/
- if(type == IMAGE_DATA_TYPE_FLOAT4 ||
- type == IMAGE_DATA_TYPE_HALF4 ||
- type == IMAGE_DATA_TYPE_BYTE4)
- {
- size_t num_pixels = ((size_t)width) * height * depth;
+ bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 ||
+ type == IMAGE_DATA_TYPE_HALF4 ||
+ type == IMAGE_DATA_TYPE_BYTE4);
+ if(is_rgba) {
if(cmyk) {
/* CMYK */
for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) {
@@ -587,14 +597,41 @@ bool ImageManager::file_load_image(Image *img,
}
}
}
+ if(pixels_storage.size() > 0) {
+ float scale_factor = 1.0f;
+ while(max_size * scale_factor > texture_limit) {
+ scale_factor *= 0.5f;
+ }
+ VLOG(1) << "Scaling image " << img->filename
+ << " by a factor of " << scale_factor << ".";
+ vector<StorageType> scaled_pixels;
+ size_t scaled_width, scaled_height, scaled_depth;
+ util_image_resize_pixels(pixels_storage,
+ width, height, depth,
+ is_rgba ? 4 : 1,
+ scale_factor,
+ &scaled_pixels,
+ &scaled_width, &scaled_height, &scaled_depth);
+ StorageType *texture_pixels = (StorageType*)tex_img.resize(scaled_width,
+ scaled_height,
+ scaled_depth);
+ memcpy(texture_pixels,
+ &scaled_pixels[0],
+ scaled_pixels.size() * sizeof(StorageType));
+ }
return true;
}
-void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progress)
+void ImageManager::device_load_image(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ ImageDataType type,
+ int slot,
+ Progress *progress)
{
if(progress->get_cancel())
return;
-
+
Image *img = images[type][slot];
if(osl_texture_system && !img->builtin_data)
@@ -603,6 +640,8 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
string filename = path_filename(images[type][slot]->filename);
progress->set_status("Updating Images", "Loading " + filename);
+ const int texture_limit = scene->params.texture_limit;
+
/* Slot assignment */
int flat_slot = type_index_to_flattened_slot(slot, type);
@@ -622,7 +661,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::FLOAT, float>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::FLOAT, float>(img,
+ type,
+ texture_limit,
+ tex_img))
+ {
/* on failure to load, we set a 1x1 pixels pink image */
float *pixels = (float*)tex_img.resize(1, 1);
@@ -648,7 +691,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::FLOAT, float>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::FLOAT, float>(img,
+ type,
+ texture_limit,
+ tex_img))
+ {
/* on failure to load, we set a 1x1 pixels pink image */
float *pixels = (float*)tex_img.resize(1, 1);
@@ -671,7 +718,11 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::UINT8, uchar>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::UINT8, uchar>(img,
+ type,
+ texture_limit,
+ tex_img))
+ {
/* on failure to load, we set a 1x1 pixels pink image */
uchar *pixels = (uchar*)tex_img.resize(1, 1);
@@ -697,7 +748,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::UINT8, uchar>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::UINT8, uchar>(img,
+ type,
+ texture_limit,
+ tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
uchar *pixels = (uchar*)tex_img.resize(1, 1);
@@ -720,7 +774,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::HALF, half>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::HALF, half>(img,
+ type,
+ texture_limit,
+ tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
half *pixels = (half*)tex_img.resize(1, 1);
@@ -746,7 +803,10 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD
device->tex_free(tex_img);
}
- if(!file_load_image<TypeDesc::HALF, half>(img, type, tex_img)) {
+ if(!file_load_image<TypeDesc::HALF, half>(img,
+ type,
+ texture_limit,
+ tex_img)) {
/* on failure to load, we set a 1x1 pixels pink image */
half *pixels = (half*)tex_img.resize(1, 1);
@@ -842,7 +902,10 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageD
}
}
-void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress& progress)
+void ImageManager::device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress)
{
if(!need_update)
return;
@@ -859,7 +922,14 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
}
else if(images[type][slot]->need_load) {
if(!osl_texture_system || images[type][slot]->builtin_data)
- pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, (ImageDataType)type, slot, &progress));
+ pool.push(function_bind(&ImageManager::device_load_image,
+ this,
+ device,
+ dscene,
+ scene,
+ (ImageDataType)type,
+ slot,
+ &progress));
}
}
}
@@ -874,6 +944,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
void ImageManager::device_update_slot(Device *device,
DeviceScene *dscene,
+ Scene *scene,
int flat_slot,
Progress *progress)
{
@@ -890,6 +961,7 @@ void ImageManager::device_update_slot(Device *device,
if(!osl_texture_system || image->builtin_data)
device_load_image(device,
dscene,
+ scene,
type,
slot,
progress);
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 1dc4bf180f8..47bbd92347c 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -30,6 +30,7 @@ CCL_NAMESPACE_BEGIN
class Device;
class DeviceScene;
class Progress;
+class Scene;
class ImageManager {
public:
@@ -67,8 +68,15 @@ public:
ExtensionType extension);
ImageDataType get_image_metadata(const string& filename, void *builtin_data, bool& is_linear);
- void device_update(Device *device, DeviceScene *dscene, Progress& progress);
- void device_update_slot(Device *device, DeviceScene *dscene, int flat_slot, Progress *progress);
+ void device_update(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ Progress& progress);
+ void device_update_slot(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ int flat_slot,
+ Progress *progress);
void device_free(Device *device, DeviceScene *dscene);
void device_free_builtin(Device *device, DeviceScene *dscene);
@@ -78,9 +86,25 @@ public:
bool need_update;
- function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
- function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
- function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
+ /* NOTE: Here pixels_size is a size of storage, which equals to
+ * width * height * depth.
+ * Use this to avoid some nasty memory corruptions.
+ */
+ function<void(const string &filename,
+ void *data,
+ bool &is_float,
+ int &width,
+ int &height,
+ int &depth,
+ int &channels)> builtin_image_info_cb;
+ function<bool(const string &filename,
+ void *data,
+ unsigned char *pixels,
+ const size_t pixels_size)> builtin_image_pixels_cb;
+ function<bool(const string &filename,
+ void *data,
+ float *pixels,
+ const size_t pixels_size)> builtin_image_float_pixels_cb;
struct Image {
string filename;
@@ -114,6 +138,7 @@ private:
typename DeviceType>
bool file_load_image(Image *img,
ImageDataType type,
+ int texture_limit,
device_vector<DeviceType>& tex_img);
int type_index_to_flattened_slot(int slot, ImageDataType type);
@@ -122,10 +147,20 @@ private:
uint8_t pack_image_options(ImageDataType type, size_t slot);
- void device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progess);
- void device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot);
-
- void device_pack_images(Device *device, DeviceScene *dscene, Progress& progess);
+ void device_load_image(Device *device,
+ DeviceScene *dscene,
+ Scene *scene,
+ ImageDataType type,
+ int slot,
+ Progress *progess);
+ void device_free_image(Device *device,
+ DeviceScene *dscene,
+ ImageDataType type,
+ int slot);
+
+ void device_pack_images(Device *device,
+ DeviceScene *dscene,
+ Progress& progess);
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index ac369a0d5f8..df4327d021a 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -1084,7 +1084,7 @@ void MeshManager::update_svm_attributes(Device *device, DeviceScene *dscene, Sce
}
/* terminator */
- for(int i = 0; i < ATTR_PRIM_TYPES; i++) {
+ for(int j = 0; j < ATTR_PRIM_TYPES; j++) {
attr_map[index].x = ATTR_STD_NONE;
attr_map[index].y = 0;
attr_map[index].z = 0;
@@ -1665,6 +1665,7 @@ void MeshManager::device_update_displacement_images(Device *device,
*/
image_manager->device_update(device,
dscene,
+ scene,
progress);
return;
}
@@ -1682,6 +1683,7 @@ void MeshManager::device_update_displacement_images(Device *device,
image_manager,
device,
dscene,
+ scene,
slot,
&progress));
}
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index f293af3c40a..3fb2bb1cf92 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -3993,7 +3993,7 @@ NODE_DEFINE(SeparateRGBNode)
SOCKET_IN_COLOR(color, "Image", make_float3(0.0f, 0.0f, 0.0f));
- SOCKET_OUT_FLOAT(g, "R");
+ SOCKET_OUT_FLOAT(r, "R");
SOCKET_OUT_FLOAT(g, "G");
SOCKET_OUT_FLOAT(b, "B");
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index b341837b7e8..68124e78cb5 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -187,7 +187,7 @@ void Scene::device_update(Device *device_, Progress& progress)
if(progress.get_cancel() || device->have_error()) return;
progress.set_status("Updating Images");
- image_manager->device_update(device, &dscene, progress);
+ image_manager->device_update(device, &dscene, this, progress);
if(progress.get_cancel() || device->have_error()) return;
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 8fec171b6fb..df9363cc768 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -145,6 +145,7 @@ public:
bool use_bvh_unaligned_nodes;
bool use_qbvh;
bool persistent_data;
+ int texture_limit;
SceneParams()
{
@@ -154,6 +155,7 @@ public:
use_bvh_unaligned_nodes = true;
use_qbvh = false;
persistent_data = false;
+ texture_limit = 0;
}
bool modified(const SceneParams& params)
@@ -162,7 +164,8 @@ public:
&& use_bvh_spatial_split == params.use_bvh_spatial_split
&& use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
&& use_qbvh == params.use_qbvh
- && persistent_data == params.persistent_data); }
+ && persistent_data == params.persistent_data
+ && texture_limit == params.texture_limit); }
};
/* Scene */
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 9d3f49a3c84..955b892f4c3 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -71,14 +71,13 @@ void SVMShaderManager::device_update_shader(Scene *scene,
scene->light_manager->need_update = true;
}
- /* We only calculate offset and do re-allocation from the locked block,
- * actual copy we do after the lock is releases to hopefully gain some
- * percent of performance.
+ /* The copy needs to be done inside the lock, if another thread resizes the array
+ * while memcpy is running, it'll be copying into possibly invalid/freed ram.
*/
nodes_lock_.lock();
size_t global_nodes_size = global_svm_nodes->size();
global_svm_nodes->resize(global_nodes_size + svm_nodes.size());
- nodes_lock_.unlock();
+
/* Offset local SVM nodes to a global address space. */
int4& jump_node = global_svm_nodes->at(shader->id);
jump_node.y = svm_nodes[0].y + global_nodes_size - 1;
@@ -88,6 +87,7 @@ void SVMShaderManager::device_update_shader(Scene *scene,
memcpy(&global_svm_nodes->at(global_nodes_size),
&svm_nodes[1],
sizeof(int4) * (svm_nodes.size() - 1));
+ nodes_lock_.unlock();
}
void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 02ee4cd6774..d8abf671bd6 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -45,6 +45,7 @@ set(SRC_HEADERS
util_half.h
util_hash.h
util_image.h
+ util_image_impl.h
util_list.h
util_logging.h
util_map.h
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index bb8a31c6fec..c8efc551d97 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -21,11 +21,25 @@
#include <OpenImageIO/imageio.h>
+#include "util_vector.h"
+
CCL_NAMESPACE_BEGIN
OIIO_NAMESPACE_USING
+template<typename T>
+void util_image_resize_pixels(const vector<T>& input_pixels,
+ const size_t input_width,
+ const size_t input_height,
+ const size_t input_depth,
+ const size_t components,
+ vector<T> *output_pixels,
+ size_t *output_width,
+ size_t *output_height,
+ size_t *output_depth);
+
CCL_NAMESPACE_END
#endif /* __UTIL_IMAGE_H__ */
+#include "util_image_impl.h"
diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h
new file mode 100644
index 00000000000..73ecfda0855
--- /dev/null
+++ b/intern/cycles/util/util_image_impl.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_IMAGE_IMPL_H__
+#define __UTIL_IMAGE_IMPL_H__
+
+#include "util_algorithm.h"
+#include "util_debug.h"
+#include "util_image.h"
+
+CCL_NAMESPACE_BEGIN
+
+namespace {
+
+template<typename T>
+const T *util_image_read(const vector<T>& pixels,
+ const size_t width,
+ const size_t height,
+ const size_t /*depth*/,
+ const size_t components,
+ const size_t x, const size_t y, const size_t z) {
+ const size_t index = ((size_t)z * (width * height) +
+ (size_t)y * width +
+ (size_t)x) * components;
+ return &pixels[index];
+}
+
+template<typename T>
+void util_image_downscale_sample(const vector<T>& pixels,
+ const size_t width,
+ const size_t height,
+ const size_t depth,
+ const size_t components,
+ const size_t kernel_size,
+ const float x,
+ const float y,
+ const float z,
+ T *result)
+{
+ assert(components <= 4);
+ const size_t ix = (size_t)x,
+ iy = (size_t)y,
+ iz = (size_t)z;
+ /* TODO(sergey): Support something smarter than box filer. */
+ float accum[4] = {0};
+ size_t count = 0;
+ for(size_t dz = 0; dz < kernel_size; ++dz) {
+ for(size_t dy = 0; dy < kernel_size; ++dy) {
+ for(size_t dx = 0; dx < kernel_size; ++dx) {
+ const size_t nx = ix + dx,
+ ny = iy + dy,
+ nz = iz + dz;
+ if(nx >= width || ny >= height || nz >= depth) {
+ continue;
+ }
+ const T *pixel = util_image_read(pixels,
+ width, height, depth,
+ components,
+ nx, ny, nz);
+ for(size_t k = 0; k < components; ++k) {
+ accum[k] += pixel[k];
+ }
+ ++count;
+ }
+ }
+ }
+ const float inv_count = 1.0f / (float)count;
+ for(size_t k = 0; k < components; ++k) {
+ result[k] = T(accum[k] * inv_count);
+ }
+}
+
+template<typename T>
+void util_image_downscale_pixels(const vector<T>& input_pixels,
+ const size_t input_width,
+ const size_t input_height,
+ const size_t input_depth,
+ const size_t components,
+ const float inv_scale_factor,
+ const size_t output_width,
+ const size_t output_height,
+ const size_t output_depth,
+ vector<T> *output_pixels)
+{
+ const size_t kernel_size = (size_t)(inv_scale_factor + 0.5f);
+ for(size_t z = 0; z < output_depth; ++z) {
+ for(size_t y = 0; y < output_height; ++y) {
+ for(size_t x = 0; x < output_width; ++x) {
+ const float input_x = (float)x * inv_scale_factor,
+ input_y = (float)y * inv_scale_factor,
+ input_z = (float)z * inv_scale_factor;
+ const size_t output_index =
+ (z * output_width * output_height +
+ y * output_width + x) * components;
+ util_image_downscale_sample(input_pixels,
+ input_width, input_height, input_depth,
+ components,
+ kernel_size,
+ input_x, input_y, input_z,
+ &output_pixels->at(output_index));
+ }
+ }
+ }
+}
+
+} /* namespace */
+
+template<typename T>
+void util_image_resize_pixels(const vector<T>& input_pixels,
+ const size_t input_width,
+ const size_t input_height,
+ const size_t input_depth,
+ const size_t components,
+ const float scale_factor,
+ vector<T> *output_pixels,
+ size_t *output_width,
+ size_t *output_height,
+ size_t *output_depth)
+{
+ /* Early output for case when no scaling is applied. */
+ if(scale_factor == 1.0f) {
+ *output_width = input_width;
+ *output_height = input_height;
+ *output_depth = input_depth;
+ *output_pixels = input_pixels;
+ return;
+ }
+ /* First of all, we calculate output image dimensions.
+ * We clamp them to be 1 pixel at least so we do not generate degenerate
+ * image.
+ */
+ *output_width = max((size_t)((float)input_width * scale_factor), (size_t)1);
+ *output_height = max((size_t)((float)input_height * scale_factor), (size_t)1);
+ *output_depth = max((size_t)((float)input_depth * scale_factor), (size_t)1);
+ /* Prepare pixel storage for the result. */
+ const size_t num_output_pixels = ((*output_width) *
+ (*output_height) *
+ (*output_depth)) * components;
+ output_pixels->resize(num_output_pixels);
+ if(scale_factor < 1.0f) {
+ const float inv_scale_factor = 1.0f / scale_factor;
+ util_image_downscale_pixels(input_pixels,
+ input_width, input_height, input_depth,
+ components,
+ inv_scale_factor,
+ *output_width, *output_height, *output_depth,
+ output_pixels);
+ } else {
+ /* TODO(sergey): Needs implementation. */
+ }
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_IMAGE_IMPL_H__ */
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index f4f460d6cf6..756bd15ed25 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -229,7 +229,7 @@ __forceinline int __btr(int v, int i) {
int r = 0; asm ("btr %1,%0" : "=r"(r) : "r"(i), "0"(v) : "flags"); return r;
}
-#if defined(__KERNEL_64_BIT__) || defined(__APPLE__)
+#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
__forceinline size_t __bsf(size_t v) {
size_t r = 0; asm ("bsf %1,%0" : "=r"(r) : "r"(v)); return r;
}
@@ -271,7 +271,7 @@ __forceinline unsigned int bitscan(unsigned int v) {
#endif
}
-#if defined(__KERNEL_64_BIT__) || defined(__APPLE__)
+#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
__forceinline size_t bitscan(size_t v) {
#if defined(__KERNEL_AVX2__)
#if defined(__KERNEL_64_BIT__)
@@ -313,7 +313,7 @@ __forceinline unsigned int __bscf(unsigned int& v)
return i;
}
-#if defined(__KERNEL_64_BIT__) || defined(__APPLE__)
+#if (defined(__KERNEL_64_BIT__) || defined(__APPLE__)) && !(defined(__ILP32__) && defined(__x86_64__))
__forceinline size_t __bscf(size_t& v)
{
size_t i = bitscan(v);
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index d5fac9a0e34..87d885c44cf 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -89,6 +89,22 @@ int system_cpu_thread_count()
return count;
}
+unsigned short system_cpu_process_groups(unsigned short max_groups,
+ unsigned short *groups)
+{
+#ifdef _WIN32
+ unsigned short group_count = max_groups;
+ if(!GetProcessGroupAffinity(GetCurrentProcess(), &group_count, groups)) {
+ return 0;
+ }
+ return group_count;
+#else
+ (void) max_groups;
+ (void) groups;
+ return 0;
+#endif
+}
+
#if !defined(_WIN32) || defined(FREE_WINDOWS)
static void __cpuid(int data[4], int selector)
{
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index 557aab6cbae..ff61b260bed 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -30,6 +30,10 @@ int system_cpu_group_thread_count(int group);
/* Get total number of threads in all groups. */
int system_cpu_thread_count();
+/* Get current process groups. */
+unsigned short system_cpu_process_groups(unsigned short max_groups,
+ unsigned short *grpups);
+
string system_cpu_brand_string();
int system_cpu_bits();
bool system_cpu_support_sse2();
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 352ba81c95a..0d1fed3ebbf 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -195,7 +195,8 @@ void TaskScheduler::init(int num_threads)
if(users == 0) {
do_exit = false;
- if(num_threads == 0) {
+ const bool use_auto_threads = (num_threads == 0);
+ if(use_auto_threads) {
/* automatic number of threads */
num_threads = system_cpu_thread_count();
}
@@ -204,7 +205,18 @@ void TaskScheduler::init(int num_threads)
/* launch threads that will be waiting for work */
threads.resize(num_threads);
- int num_groups = system_cpu_group_count();
+ const int num_groups = system_cpu_group_count();
+ unsigned short num_process_groups;
+ vector<unsigned short> process_groups;
+ int current_group_threads;
+ if(num_groups > 1) {
+ process_groups.resize(num_groups);
+ num_process_groups = system_cpu_process_groups(num_groups,
+ &process_groups[0]);
+ if(num_process_groups == 1) {
+ current_group_threads = system_cpu_group_thread_count(process_groups[0]);
+ }
+ }
int thread_index = 0;
for(int group = 0; group < num_groups; ++group) {
/* NOTE: That's not really efficient from threading point of view,
@@ -218,9 +230,25 @@ void TaskScheduler::init(int num_threads)
group_thread < num_group_threads && thread_index < threads.size();
++group_thread, ++thread_index)
{
+ /* NOTE: Thread group of -1 means we would not force thread affinity. */
+ int thread_group;
+ if(num_groups == 1) {
+ /* Use default affinity if there's only one CPU group in the system. */
+ thread_group = -1;
+ }
+ else if(use_auto_threads &&
+ num_process_groups == 1 &&
+ num_threads <= current_group_threads)
+ {
+ /* If we fit into curent CPU group we also don't force any affinity. */
+ thread_group = -1;
+ }
+ else {
+ thread_group = group;
+ }
threads[thread_index] = new thread(function_bind(&TaskScheduler::thread_run,
thread_index + 1),
- group);
+ thread_group);
}
}
}
diff --git a/intern/cycles/util/util_windows.cpp b/intern/cycles/util/util_windows.cpp
index ee5b3fd73c0..4de8483564b 100644
--- a/intern/cycles/util/util_windows.cpp
+++ b/intern/cycles/util/util_windows.cpp
@@ -28,6 +28,7 @@ CCL_NAMESPACE_BEGIN
tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
tGetActiveProcessorCount *GetActiveProcessorCount;
tSetThreadGroupAffinity *SetThreadGroupAffinity;
+tGetProcessGroupAffinity *GetProcessGroupAffinity;
#endif
static WORD GetActiveProcessorGroupCount_stub()
@@ -50,6 +51,18 @@ static BOOL SetThreadGroupAffinity_stub(
return TRUE;
}
+static BOOL GetProcessGroupAffinity_stub(HANDLE hProcess,
+ PUSHORT GroupCount,
+ PUSHORT GroupArray)
+{
+ if(*GroupCount < 1) {
+ return FALSE;
+ }
+ *GroupCount = 1;
+ GroupArray[0] = 0;
+ return TRUE;
+}
+
static bool supports_numa()
{
#ifndef _M_X64
@@ -72,6 +85,7 @@ void util_windows_init_numa_groups()
GetActiveProcessorGroupCount = GetActiveProcessorGroupCount_stub;
GetActiveProcessorCount = GetActiveProcessorCount_stub;
SetThreadGroupAffinity = SetThreadGroupAffinity_stub;
+ GetProcessGroupAffinity = GetProcessGroupAffinity_stub;
return;
}
HMODULE kernel = GetModuleHandleA("kernel32.dll");
@@ -79,6 +93,7 @@ void util_windows_init_numa_groups()
READ_SYMBOL(GetActiveProcessorGroupCount);
READ_SYMBOL(GetActiveProcessorCount);
READ_SYMBOL(SetThreadGroupAffinity);
+ READ_SYMBOL(GetProcessGroupAffinity);
# undef READ_SUMBOL
#endif
}
diff --git a/intern/cycles/util/util_windows.h b/intern/cycles/util/util_windows.h
index ac61d5348c3..7ea3e65c2c5 100644
--- a/intern/cycles/util/util_windows.h
+++ b/intern/cycles/util/util_windows.h
@@ -39,10 +39,14 @@ typedef DWORD tGetActiveProcessorCount(WORD GroupNumber);
typedef BOOL tSetThreadGroupAffinity(HANDLE hThread,
const GROUP_AFFINITY *GroupAffinity,
PGROUP_AFFINITY PreviousGroupAffinity);
+typedef BOOL tGetProcessGroupAffinity(HANDLE hProcess,
+ PUSHORT GroupCount,
+ PUSHORT GroupArray);
extern tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
extern tGetActiveProcessorCount *GetActiveProcessorCount;
extern tSetThreadGroupAffinity *SetThreadGroupAffinity;
+extern tGetProcessGroupAffinity *GetProcessGroupAffinity;
#endif
/* Make sure NUMA and processor groups API is initialized. */
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 1f49adecdef..58aa0b87045 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -353,7 +353,7 @@ GHOST_WindowWin32::~GHOST_WindowWin32()
// Release our reference of the DropTarget and it will delete itself eventually.
m_dropTarget->Release();
}
-
+ ::SetWindowLongPtr(m_hWnd, GWLP_USERDATA, NULL);
::DestroyWindow(m_hWnd);
m_hWnd = 0;
}
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index a02117d517e..992200a0b09 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -861,24 +861,32 @@ void GHOST_WindowX11::icccmSetState(int state)
int GHOST_WindowX11::icccmGetState(void) const
{
- Atom *prop_ret;
+ struct {
+ CARD32 state;
+ XID icon;
+ } *prop_ret;
unsigned long bytes_after, num_ret;
Atom type_ret;
- int format_ret, st;
+ int ret, format_ret;
+ CARD32 st;
prop_ret = NULL;
- st = XGetWindowProperty(
+ ret = XGetWindowProperty(
m_display, m_window, m_system->m_atom.WM_STATE, 0, 2,
False, m_system->m_atom.WM_STATE, &type_ret,
&format_ret, &num_ret, &bytes_after, ((unsigned char **)&prop_ret));
- if ((st == Success) && (prop_ret) && (num_ret == 2))
- st = prop_ret[0];
- else
+ if ((ret == Success) && (prop_ret != NULL) && (num_ret == 2)) {
+ st = prop_ret->state;
+ }
+ else {
st = NormalState;
+ }
- if (prop_ret)
+ if (prop_ret) {
XFree(prop_ret);
- return (st);
+ }
+
+ return st;
}
void GHOST_WindowX11::netwmMaximized(bool set)
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 1124e7fd8ab..d0a129360b0 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -77,7 +77,8 @@ int FallbackImpl::configGetNumColorSpaces(OCIO_ConstConfigRcPtr * /*config*/)
return 2;
}
-const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/, int index)
+const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr * /*config*/,
+ int index)
{
if (index == 0)
return "Linear";
@@ -87,7 +88,8 @@ const char *FallbackImpl::configGetColorSpaceNameByIndex(OCIO_ConstConfigRcPtr *
return NULL;
}
-OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/, const char *name)
+OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcPtr * /*config*/,
+ const char *name)
{
if (strcmp(name, "scene_linear") == 0)
return COLORSPACE_LINEAR;
@@ -109,15 +111,17 @@ OCIO_ConstColorSpaceRcPtr *FallbackImpl::configGetColorSpace(OCIO_ConstConfigRcP
return NULL;
}
-int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *name)
+int FallbackImpl::configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config,
+ const char *name)
{
OCIO_ConstColorSpaceRcPtr *cs = configGetColorSpace(config, name);
- if (cs == COLORSPACE_LINEAR)
+ if (cs == COLORSPACE_LINEAR) {
return 0;
- else if (cs == COLORSPACE_SRGB)
+ }
+ else if (cs == COLORSPACE_SRGB) {
return 1;
-
+ }
return -1;
}
@@ -131,44 +135,51 @@ int FallbackImpl::configGetNumDisplays(OCIO_ConstConfigRcPtr * /*config*/)
return 1;
}
-const char *FallbackImpl::configGetDisplay(OCIO_ConstConfigRcPtr * /*config*/, int index)
+const char *FallbackImpl::configGetDisplay(OCIO_ConstConfigRcPtr * /*config*/,
+ int index)
{
- if (index == 0)
+ if (index == 0) {
return "sRGB";
-
+ }
return NULL;
}
-const char *FallbackImpl::configGetDefaultView(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/)
+const char *FallbackImpl::configGetDefaultView(OCIO_ConstConfigRcPtr * /*config*/,
+ const char * /*display*/)
{
return "Default";
}
-int FallbackImpl::configGetNumViews(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/)
+int FallbackImpl::configGetNumViews(OCIO_ConstConfigRcPtr * /*config*/,
+ const char * /*display*/)
{
return 1;
}
-const char *FallbackImpl::configGetView(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/, int index)
+const char *FallbackImpl::configGetView(OCIO_ConstConfigRcPtr * /*config*/,
+ const char * /*display*/, int index)
{
- if (index == 0)
+ if (index == 0) {
return "Default";
-
+ }
return NULL;
}
-const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr * /*config*/, const char * /*display*/, const char * /*view*/)
+const char *FallbackImpl::configGetDisplayColorSpaceName(OCIO_ConstConfigRcPtr * /*config*/,
+ const char * /*display*/,
+ const char * /*view*/)
{
return "sRGB";
}
-void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, float *rgb)
+void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/,
+ float *rgb)
{
- /* Here we simply use the older Blender assumed primaries of
- * ITU-BT.709 / sRGB, or 0.2126729 0.7151522 0.0721750. Brute
- * force stupid, but only plausible option given no color management
- * system in place.
- */
+ /* Here we simply use the older Blender assumed primaries of
+ * ITU-BT.709 / sRGB, or 0.2126729 0.7151522 0.0721750. Brute
+ * force stupid, but only plausible option given no color management
+ * system in place.
+ */
rgb[0] = 0.2126f;
rgb[1] = 0.7152f;
@@ -180,12 +191,14 @@ int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/)
return 0;
}
-const char *FallbackImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr * /*config*/, int /*index*/)
+const char *FallbackImpl::configGetLookNameByIndex(OCIO_ConstConfigRcPtr * /*config*/,
+ int /*index*/)
{
return "";
}
-OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*config*/, const char * /*name*/)
+OCIO_ConstLookRcPtr *FallbackImpl::configGetLook(OCIO_ConstConfigRcPtr * /*config*/,
+ const char * /*name*/)
{
return NULL;
}
@@ -213,25 +226,30 @@ void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
{
}
-OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(OCIO_ConstConfigRcPtr *config, const char *srcName, const char *dstName)
+OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessorWithNames(
+ OCIO_ConstConfigRcPtr *config,
+ const char *srcName,
+ const char *dstName)
{
OCIO_ConstColorSpaceRcPtr *cs_src = configGetColorSpace(config, srcName);
OCIO_ConstColorSpaceRcPtr *cs_dst = configGetColorSpace(config, dstName);
-
- if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB)
+ if (cs_src == COLORSPACE_LINEAR && cs_dst == COLORSPACE_SRGB) {
return PROCESSOR_LINEAR_TO_SRGB;
- else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR)
+ }
+ else if (cs_src == COLORSPACE_SRGB && cs_dst == COLORSPACE_LINEAR) {
return PROCESSOR_SRGB_TO_LINEAR;
-
+ }
return 0;
}
-OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/, OCIO_ConstTransformRcPtr *tfm)
+OCIO_ConstProcessorRcPtr *FallbackImpl::configGetProcessor(OCIO_ConstConfigRcPtr * /*config*/,
+ OCIO_ConstTransformRcPtr *tfm)
{
return (OCIO_ConstProcessorRcPtr*)tfm;
}
-void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
+void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor,
+ OCIO_PackedImageDesc *img)
{
/* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
@@ -253,7 +271,8 @@ void FallbackImpl::processorApply(OCIO_ConstProcessorRcPtr *processor, OCIO_Pack
}
}
-void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor, OCIO_PackedImageDesc *img)
+void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
+ OCIO_PackedImageDesc *img)
{
/* OCIO_TODO stride not respected, channels must be 3 or 4 */
OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)img;
@@ -275,15 +294,19 @@ void FallbackImpl::processorApply_predivide(OCIO_ConstProcessorRcPtr *processor,
}
}
-void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor, float *pixel)
+void FallbackImpl::processorApplyRGB(OCIO_ConstProcessorRcPtr *processor,
+ float *pixel)
{
- if (processor == PROCESSOR_LINEAR_TO_SRGB)
+ if (processor == PROCESSOR_LINEAR_TO_SRGB) {
linearrgb_to_srgb_v3_v3(pixel, pixel);
- else if (processor == PROCESSOR_SRGB_TO_LINEAR)
+ }
+ else if (processor == PROCESSOR_SRGB_TO_LINEAR) {
srgb_to_linearrgb_v3_v3(pixel, pixel);
+ }
}
-void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float *pixel)
+void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor,
+ float *pixel)
{
if (processor == PROCESSOR_LINEAR_TO_SRGB)
linearrgb_to_srgb_v4(pixel, pixel);
@@ -291,7 +314,8 @@ void FallbackImpl::processorApplyRGBA(OCIO_ConstProcessorRcPtr *processor, float
srgb_to_linearrgb_v4(pixel, pixel);
}
-void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor, float *pixel)
+void FallbackImpl::processorApplyRGBA_predivide(OCIO_ConstProcessorRcPtr *processor,
+ float *pixel)
{
if (pixel[3] == 1.0f || pixel[3] == 0.0f) {
processorApplyRGBA(processor, pixel);
@@ -320,11 +344,12 @@ void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr * /*p*/)
const char *FallbackImpl::colorSpaceGetName(OCIO_ConstColorSpaceRcPtr *cs)
{
- if (cs == COLORSPACE_LINEAR)
+ if (cs == COLORSPACE_LINEAR) {
return "Linear";
- else if (cs == COLORSPACE_SRGB)
+ }
+ else if (cs == COLORSPACE_SRGB) {
return "sRGB";
-
+ }
return NULL;
}
@@ -343,31 +368,38 @@ OCIO_DisplayTransformRcPtr *FallbackImpl::createDisplayTransform(void)
return (OCIO_DisplayTransformRcPtr*)PROCESSOR_LINEAR_TO_SRGB;
}
-void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
+void FallbackImpl::displayTransformSetInputColorSpaceName(OCIO_DisplayTransformRcPtr * /*dt*/,
+ const char * /*name*/)
{
}
-void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
+void FallbackImpl::displayTransformSetDisplay(OCIO_DisplayTransformRcPtr * /*dt*/,
+ const char * /*name*/)
{
}
-void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*name*/)
+void FallbackImpl::displayTransformSetView(OCIO_DisplayTransformRcPtr * /*dt*/,
+ const char * /*name*/)
{
}
-void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr * /*dt*/, OCIO_ConstTransformRcPtr * /*et*/)
+void FallbackImpl::displayTransformSetDisplayCC(OCIO_DisplayTransformRcPtr * /*dt*/,
+ OCIO_ConstTransformRcPtr * /*et*/)
{
}
-void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr * /*dt*/, OCIO_ConstTransformRcPtr * /*et*/)
+void FallbackImpl::displayTransformSetLinearCC(OCIO_DisplayTransformRcPtr * /*dt*/,
+ OCIO_ConstTransformRcPtr * /*et*/)
{
}
-void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/, const char * /*looks*/)
+void FallbackImpl::displayTransformSetLooksOverride(OCIO_DisplayTransformRcPtr * /*dt*/,
+ const char * /*looks*/)
{
}
-void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/, bool /*enabled*/)
+void FallbackImpl::displayTransformSetLooksOverrideEnabled(OCIO_DisplayTransformRcPtr * /*dt*/,
+ bool /*enabled*/)
{
}
@@ -375,11 +407,14 @@ void FallbackImpl::displayTransformRelease(OCIO_DisplayTransformRcPtr * /*dt*/)
{
}
-OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long width, long height, long numChannels,
- long chanStrideBytes, long xStrideBytes, long yStrideBytes)
+OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(
+ float *data,
+ long width, long height, long numChannels,
+ long chanStrideBytes, long xStrideBytes, long yStrideBytes)
{
- OCIO_PackedImageDescription *desc = (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription), "OCIO_PackedImageDescription");
-
+ OCIO_PackedImageDescription *desc =
+ (OCIO_PackedImageDescription*)MEM_callocN(sizeof(OCIO_PackedImageDescription),
+ "OCIO_PackedImageDescription");
desc->data = data;
desc->width = width;
desc->height = height;
@@ -387,7 +422,6 @@ OCIO_PackedImageDesc *FallbackImpl::createOCIO_PackedImageDesc(float *data, long
desc->chanStrideBytes = chanStrideBytes;
desc->xStrideBytes = xStrideBytes;
desc->yStrideBytes = yStrideBytes;
-
return (OCIO_PackedImageDesc*)desc;
}
@@ -401,7 +435,8 @@ OCIO_ExponentTransformRcPtr *FallbackImpl::createExponentTransform(void)
return (OCIO_ExponentTransformRcPtr*)PROCESSOR_UNKNOWN;
}
-void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr * /*et*/, const float * /*exponent*/)
+void FallbackImpl::exponentTransformSetValue(OCIO_ExponentTransformRcPtr * /*et*/,
+ const float * /*exponent*/)
{
}
@@ -414,7 +449,9 @@ OCIO_MatrixTransformRcPtr *FallbackImpl::createMatrixTransform(void)
return (OCIO_MatrixTransformRcPtr*)PROCESSOR_UNKNOWN;
}
-void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr * /*mt*/, const float * /*m44*/, const float * /*offset4*/)
+void FallbackImpl::matrixTransformSetValue(OCIO_MatrixTransformRcPtr * /*mt*/,
+ const float * /*m44*/,
+ const float * /*offset4*/)
{
}
@@ -422,7 +459,9 @@ void FallbackImpl::matrixTransformRelease(OCIO_MatrixTransformRcPtr * /*mt*/)
{
}
-void FallbackImpl::matrixTransformScale(float * /*m44*/, float * /*offset44*/, const float * /*scale4*/)
+void FallbackImpl::matrixTransformScale(float * /*m44*/,
+ float * /*offset44*/,
+ const float * /*scale4*/)
{
}
@@ -431,9 +470,11 @@ bool FallbackImpl::supportGLSLDraw(void)
return false;
}
-bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/, OCIO_ConstProcessorRcPtr * /*processor*/,
+bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState ** /*state_r*/,
+ OCIO_ConstProcessorRcPtr * /*processor*/,
OCIO_CurveMappingSettings * /*curve_mapping_settings*/,
- float /*dither*/, bool /*predivide*/)
+ float /*dither*/,
+ bool /*predivide*/)
{
return false;
}
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index f12e7484e64..247b91e147f 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -32,25 +32,24 @@ from bpy_extras import object_utils
def add_torus(major_rad, minor_rad, major_seg, minor_seg):
from math import cos, sin, pi
- from mathutils import Vector, Quaternion
+ from mathutils import Vector, Matrix
- PI_2 = pi * 2.0
- z_axis = 0.0, 0.0, 1.0
+ pi_2 = pi * 2.0
verts = []
faces = []
i1 = 0
tot_verts = major_seg * minor_seg
for major_index in range(major_seg):
- quat = Quaternion(z_axis, (major_index / major_seg) * PI_2)
+ matrix = Matrix.Rotation((major_index / major_seg) * pi_2, 3, 'Z')
for minor_index in range(minor_seg):
- angle = 2 * pi * minor_index / minor_seg
+ angle = pi_2 * minor_index / minor_seg
- vec = quat * Vector((major_rad + (cos(angle) * minor_rad),
- 0.0,
- (sin(angle) * minor_rad),
- ))
+ vec = matrix * Vector((major_rad + (cos(angle) * minor_rad),
+ 0.0,
+ sin(angle) * minor_rad,
+ ))
verts.extend(vec[:])
@@ -58,7 +57,6 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
i2 = (major_index) * minor_seg
i3 = i1 + minor_seg
i4 = i2 + minor_seg
-
else:
i2 = i1 + 1
i3 = i1 + minor_seg
@@ -71,11 +69,7 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
if i4 >= tot_verts:
i4 = i4 - tot_verts
- # stupid eekadoodle
- if i2:
- faces.extend([i1, i3, i4, i2])
- else:
- faces.extend([i2, i1, i3, i4])
+ faces.extend([i1, i3, i4, i2])
i1 += 1
@@ -83,31 +77,56 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
def add_uvs(mesh, minor_seg, major_seg):
+ from math import fmod
+
mesh.uv_textures.new()
uv_data = mesh.uv_layers.active.data
polygons = mesh.polygons
u_step = 1.0 / major_seg
v_step = 1.0 / minor_seg
+
+ # Round UV's, needed when segments aren't divisible by 4.
+ u_init = 0.5 + fmod(0.5, u_step)
+ v_init = 0.5 + fmod(0.5, v_step)
+
+ # Calculate wrapping value under 1.0 to prevent
+ # float precision errors wrapping at the wrong step.
+ u_wrap = 1.0 - (u_step / 2.0)
+ v_wrap = 1.0 - (v_step / 2.0)
+
vertex_index = 0
- u = 0.5
+ u_prev = u_init
+ u_next = u_prev + u_step
for major_index in range(major_seg):
- v = 0.5
+ v_prev = v_init
+ v_next = v_prev + v_step
for minor_index in range(minor_seg):
loops = polygons[vertex_index].loop_indices
if minor_index == minor_seg - 1 and major_index == 0:
- uv_data[loops[1]].uv = (u, v)
- uv_data[loops[2]].uv = (u + u_step, v)
- uv_data[loops[0]].uv = (u, v + v_step)
- uv_data[loops[3]].uv = (u + u_step, v + v_step)
+ uv_data[loops[1]].uv = u_prev, v_prev
+ uv_data[loops[2]].uv = u_next, v_prev
+ uv_data[loops[0]].uv = u_prev, v_next
+ uv_data[loops[3]].uv = u_next, v_next
else:
- uv_data[loops[0]].uv = (u, v)
- uv_data[loops[1]].uv = (u + u_step, v)
- uv_data[loops[3]].uv = (u, v + v_step)
- uv_data[loops[2]].uv = (u + u_step, v + v_step)
- v = (v + v_step) % 1.0
+ uv_data[loops[0]].uv = u_prev, v_prev
+ uv_data[loops[1]].uv = u_next, v_prev
+ uv_data[loops[3]].uv = u_prev, v_next
+ uv_data[loops[2]].uv = u_next, v_next
+
+ if v_next > v_wrap:
+ v_prev = v_next - 1.0
+ else:
+ v_prev = v_next
+ v_next = v_prev + v_step
+
vertex_index += 1
- u = (u + u_step) % 1.0
+
+ if u_next > u_wrap:
+ u_prev = u_next - 1.0
+ else:
+ u_prev = u_next
+ u_next = u_prev + u_step
class AddTorus(Operator, object_utils.AddObjectHelper):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 1cbc0410829..94d7777ad1b 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -428,6 +428,12 @@ class USERPREF_PT_system(Panel):
col.separator()
+ if bpy.app.build_options.cycles:
+ addon = userpref.addons.get("cycles")
+ if addon is not None:
+ addon.preferences.draw_impl(col, context)
+ del addon
+
if hasattr(system, "opensubdiv_compute_type"):
col.label(text="OpenSubdiv compute:")
col.row().prop(system, "opensubdiv_compute_type", text="")
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_camera.cc
index d5271e3ca31..4f70b2a972c 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_camera.cc
@@ -138,11 +138,11 @@ void AbcCameraReader::readObjectData(Main *bmain, float time)
bcam->stereo.convergence_distance = convergence_plane.getValue(sample_sel);
}
- const float lens = cam_sample.getFocalLength();
- const float apperture_x = cam_sample.getHorizontalAperture();
- const float apperture_y = cam_sample.getVerticalAperture();
- const float h_film_offset = cam_sample.getHorizontalFilmOffset();
- const float v_film_offset = cam_sample.getVerticalFilmOffset();
+ const float lens = static_cast<float>(cam_sample.getFocalLength());
+ const float apperture_x = static_cast<float>(cam_sample.getHorizontalAperture());
+ const float apperture_y = static_cast<float>(cam_sample.getVerticalAperture());
+ const float h_film_offset = static_cast<float>(cam_sample.getHorizontalFilmOffset());
+ const float v_film_offset = static_cast<float>(cam_sample.getVerticalFilmOffset());
const float film_aspect = apperture_x / apperture_y;
bcam->lens = lens;
@@ -150,10 +150,10 @@ void AbcCameraReader::readObjectData(Main *bmain, float time)
bcam->sensor_y = apperture_y * 10;
bcam->shiftx = h_film_offset / apperture_x;
bcam->shifty = v_film_offset / apperture_y / film_aspect;
- bcam->clipsta = max_ff(0.1f, cam_sample.getNearClippingPlane());
- bcam->clipend = cam_sample.getFarClippingPlane();
- bcam->gpu_dof.focus_distance = cam_sample.getFocusDistance();
- bcam->gpu_dof.fstop = cam_sample.getFStop();
+ bcam->clipsta = max_ff(0.1f, static_cast<float>(cam_sample.getNearClippingPlane()));
+ bcam->clipend = static_cast<float>(cam_sample.getFarClippingPlane());
+ bcam->gpu_dof.focus_distance = static_cast<float>(cam_sample.getFocusDistance());
+ bcam->gpu_dof.fstop = static_cast<float>(cam_sample.getFStop());
m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str());
m_object->data = bcam;
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 7e5ea3b1853..4ecb9d944f2 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -361,7 +361,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
* object directly and create a new DerivedMesh from that. Also we might need to
* create new or delete existing NURBS in the curve.
*/
-DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/)
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/, const char **/*err_str*/)
{
ISampleSelector sample_sel(time);
const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h
index 979ee8af639..2757d179a47 100644
--- a/source/blender/alembic/intern/abc_curves.h
+++ b/source/blender/alembic/intern/abc_curves.h
@@ -56,7 +56,7 @@ public:
bool valid() const;
void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *, const float time, int);
+ DerivedMesh *read_derivedmesh(DerivedMesh *, const float time, int read_flag, const char **err_str);
};
/* ************************************************************************** */
diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h
index bc42e24eba1..9e671fde386 100644
--- a/source/blender/alembic/intern/abc_customdata.h
+++ b/source/blender/alembic/intern/abc_customdata.h
@@ -26,6 +26,7 @@
#define __ABC_CUSTOMDATA_H__
#include <Alembic/Abc/All.h>
+#include <Alembic/AbcGeom/All.h>
struct CustomData;
struct MLoop;
@@ -65,8 +66,8 @@ struct CDStreamConfig {
float weight;
float time;
- int index;
- int ceil_index;
+ Alembic::AbcGeom::index_t index;
+ Alembic::AbcGeom::index_t ceil_index;
CDStreamConfig()
: mloop(NULL)
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 5e66d6c2dc7..92fee170e29 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -175,13 +175,13 @@ void AbcExporter::getShutterSamples(double step, bool time_relative,
/* sample all frame */
if (shutter_open == 0.0 && shutter_close == 1.0) {
- for (double t = 0; t < 1.0; t += step) {
+ for (double t = 0.0; t < 1.0; t += step) {
samples.push_back((t + m_settings.frame_start) / time_factor);
}
}
else {
/* sample between shutter open & close */
- const int nsamples = std::max((1.0 / step) - 1.0, 1.0);
+ const int nsamples = static_cast<int>(std::max((1.0 / step) - 1.0, 1.0));
const double time_inc = (shutter_close - shutter_open) / nsamples;
for (double t = shutter_open; t <= shutter_close; t += time_inc) {
@@ -216,7 +216,7 @@ void AbcExporter::getFrameSet(double step, std::set<double> &frames)
getShutterSamples(step, false, shutter_samples);
- for (int frame = m_settings.frame_start; frame <= m_settings.frame_end; ++frame) {
+ for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) {
for (int j = 0, e = shutter_samples.size(); j < e; ++j) {
frames.insert(frame + shutter_samples[j]);
}
@@ -237,9 +237,9 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
}
Scene *scene = m_scene;
- const int fps = FPS;
+ const double fps = FPS;
char buf[16];
- snprintf(buf, 15, "%d", fps);
+ snprintf(buf, 15, "%f", fps);
const std::string str_fps = buf;
Alembic::AbcCoreAbstract::MetaData md;
@@ -561,7 +561,7 @@ AbcTransformWriter *AbcExporter::getXForm(const std::string &name)
void AbcExporter::setCurrentFrame(Main *bmain, double t)
{
- m_scene->r.cfra = std::floor(t);
- m_scene->r.subframe = t - m_scene->r.cfra;
+ m_scene->r.cfra = static_cast<int>(t);
+ m_scene->r.subframe = static_cast<float>(t) - m_scene->r.cfra;
BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, m_scene, m_scene->lay);
}
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 3d80756fcca..ad0d0a430c1 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -868,53 +868,6 @@ ABC_INLINE void read_normals_params(AbcMeshData &abc_data,
}
}
-/* ************************************************************************** */
-
-AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings)
- : AbcObjectReader(object, settings)
-{
- m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
-
- IPolyMesh ipoly_mesh(m_iobject, kWrapExisting);
- m_schema = ipoly_mesh.getSchema();
-
- get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
-}
-
-bool AbcMeshReader::valid() const
-{
- return m_schema.valid();
-}
-
-void AbcMeshReader::readObjectData(Main *bmain, float time)
-{
- Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
-
- m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
- m_object->data = mesh;
-
- const ISampleSelector sample_sel(time);
-
- DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL);
-
- if (ndm != dm) {
- dm->release(dm);
- }
-
- DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
-
- if (m_settings->validate_meshes) {
- BKE_mesh_validate(mesh, false, false);
- }
-
- readFaceSetsSample(bmain, mesh, 0, sample_sel);
-
- if (has_animations(m_schema, m_settings)) {
- addCacheModifier();
- }
-}
-
static bool check_smooth_poly_flag(DerivedMesh *dm)
{
MPoly *mpolys = dm->getPolyArray(dm);
@@ -962,6 +915,66 @@ static void *add_customdata_cb(void *user_data, const char *name, int data_type)
return cd_ptr;
}
+static void get_weight_and_index(CDStreamConfig &config,
+ Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
+ size_t samples_number)
+{
+ Alembic::AbcGeom::index_t i0, i1;
+
+ config.weight = get_weight_and_index(config.time,
+ time_sampling,
+ samples_number,
+ i0,
+ i1);
+
+ config.index = i0;
+ config.ceil_index = i1;
+}
+
+static void read_mesh_sample(ImportSettings *settings,
+ const IPolyMeshSchema &schema,
+ const ISampleSelector &selector,
+ CDStreamConfig &config,
+ bool &do_normals)
+{
+ const IPolyMeshSchema::Sample sample = schema.getValue(selector);
+
+ AbcMeshData abc_mesh_data;
+ abc_mesh_data.face_counts = sample.getFaceCounts();
+ abc_mesh_data.face_indices = sample.getFaceIndices();
+ abc_mesh_data.positions = sample.getPositions();
+
+ read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector);
+
+ do_normals = (abc_mesh_data.face_normals != NULL);
+
+ get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
+
+ if (config.weight != 0.0f) {
+ Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
+ schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
+ abc_mesh_data.ceil_positions = ceil_sample.getPositions();
+ }
+
+ if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
+ read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
+ }
+
+ if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
+ read_mverts(config, abc_mesh_data);
+ }
+
+ if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
+ read_mpolys(config, abc_mesh_data);
+ }
+
+ if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
+ read_custom_data(schema.getArbGeomParams(), config, selector);
+ }
+
+ /* TODO: face sets */
+}
+
CDStreamConfig get_config(DerivedMesh *dm)
{
CDStreamConfig config;
@@ -978,7 +991,54 @@ CDStreamConfig get_config(DerivedMesh *dm)
return config;
}
-DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+/* ************************************************************************** */
+
+AbcMeshReader::AbcMeshReader(const IObject &object, ImportSettings &settings)
+ : AbcObjectReader(object, settings)
+{
+ m_settings->read_flag |= MOD_MESHSEQ_READ_ALL;
+
+ IPolyMesh ipoly_mesh(m_iobject, kWrapExisting);
+ m_schema = ipoly_mesh.getSchema();
+
+ get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
+}
+
+bool AbcMeshReader::valid() const
+{
+ return m_schema.valid();
+}
+
+void AbcMeshReader::readObjectData(Main *bmain, float time)
+{
+ Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
+
+ m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str());
+ m_object->data = mesh;
+
+ const ISampleSelector sample_sel(time);
+
+ DerivedMesh *dm = CDDM_from_mesh(mesh);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL);
+
+ if (ndm != dm) {
+ dm->release(dm);
+ }
+
+ DM_to_mesh(ndm, mesh, m_object, CD_MASK_MESH, true);
+
+ if (m_settings->validate_meshes) {
+ BKE_mesh_validate(mesh, false, false);
+ }
+
+ readFaceSetsSample(bmain, mesh, 0, sample_sel);
+
+ if (has_animations(m_schema, m_settings)) {
+ addCacheModifier();
+ }
+}
+
+DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
{
ISampleSelector sample_sel(time);
const IPolyMeshSchema::Sample sample = m_schema.getValue(sample_sel);
@@ -1003,6 +1063,21 @@ DerivedMesh *AbcMeshReader::read_derivedmesh(DerivedMesh *dm, const float time,
settings.read_flag |= MOD_MESHSEQ_READ_ALL;
}
+ else {
+ /* If the face count changed (e.g. by triangulation), only read points.
+ * This prevents crash from T49813.
+ * TODO(kevin): perhaps find a better way to do this? */
+ if (face_counts->size() != dm->getNumPolys(dm) ||
+ face_indices->size() != dm->getNumLoops(dm))
+ {
+ settings.read_flag = MOD_MESHSEQ_READ_VERT;
+
+ if (err_str) {
+ *err_str = "Topology has changed, perhaps by triangulating the"
+ " mesh. Only vertices will be read!";
+ }
+ }
+ }
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
config.time = time;
@@ -1078,44 +1153,40 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star
utils::assign_materials(bmain, m_object, mat_map);
}
-static void get_weight_and_index(CDStreamConfig &config,
- Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling,
- size_t samples_number)
+/* ************************************************************************** */
+
+ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
{
- Alembic::AbcGeom::index_t i0, i1;
+ for (int i = 0, e = totedge; i < e; ++i) {
+ MEdge &edge = edges[i];
- config.weight = get_weight_and_index(config.time,
- time_sampling,
- samples_number,
- i0,
- i1);
+ if (edge.v1 == v1 && edge.v2 == v2) {
+ return &edge;
+ }
+ }
- config.index = i0;
- config.ceil_index = i1;
+ return NULL;
}
-void read_mesh_sample(ImportSettings *settings,
- const IPolyMeshSchema &schema,
- const ISampleSelector &selector,
- CDStreamConfig &config,
- bool &do_normals)
+static void read_subd_sample(ImportSettings *settings,
+ const ISubDSchema &schema,
+ const ISampleSelector &selector,
+ CDStreamConfig &config)
{
- const IPolyMeshSchema::Sample sample = schema.getValue(selector);
+ const ISubDSchema::Sample sample = schema.getValue(selector);
AbcMeshData abc_mesh_data;
abc_mesh_data.face_counts = sample.getFaceCounts();
abc_mesh_data.face_indices = sample.getFaceIndices();
+ abc_mesh_data.vertex_normals = N3fArraySamplePtr();
+ abc_mesh_data.face_normals = N3fArraySamplePtr();
abc_mesh_data.positions = sample.getPositions();
- read_normals_params(abc_mesh_data, schema.getNormalsParam(), selector);
-
- do_normals = (abc_mesh_data.face_normals != NULL);
-
get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
if (config.weight != 0.0f) {
- Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample;
- schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
+ Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
+ schema.get(ceil_sample, Alembic::Abc::ISampleSelector(config.ceil_index));
abc_mesh_data.ceil_positions = ceil_sample.getPositions();
}
@@ -1140,19 +1211,6 @@ void read_mesh_sample(ImportSettings *settings,
/* ************************************************************************** */
-ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
-{
- for (int i = 0, e = totedge; i < e; ++i) {
- MEdge &edge = edges[i];
-
- if (edge.v1 == v1 && edge.v2 == v2) {
- return &edge;
- }
- }
-
- return NULL;
-}
-
AbcSubDReader::AbcSubDReader(const IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -1177,7 +1235,7 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
m_object->data = mesh;
DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, MOD_MESHSEQ_READ_ALL, NULL);
if (ndm != dm) {
dm->release(dm);
@@ -1216,48 +1274,7 @@ void AbcSubDReader::readObjectData(Main *bmain, float time)
}
}
-void read_subd_sample(ImportSettings *settings,
- const ISubDSchema &schema,
- const ISampleSelector &selector,
- CDStreamConfig &config)
-{
- const ISubDSchema::Sample sample = schema.getValue(selector);
-
- AbcMeshData abc_mesh_data;
- abc_mesh_data.face_counts = sample.getFaceCounts();
- abc_mesh_data.face_indices = sample.getFaceIndices();
- abc_mesh_data.vertex_normals = N3fArraySamplePtr();
- abc_mesh_data.face_normals = N3fArraySamplePtr();
- abc_mesh_data.positions = sample.getPositions();
-
- get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples());
-
- if (config.weight != 0.0f) {
- Alembic::AbcGeom::ISubDSchema::Sample ceil_sample;
- schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index)));
- abc_mesh_data.ceil_positions = ceil_sample.getPositions();
- }
-
- if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) {
- read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector);
- }
-
- if ((settings->read_flag & MOD_MESHSEQ_READ_VERT) != 0) {
- read_mverts(config, abc_mesh_data);
- }
-
- if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
- read_mpolys(config, abc_mesh_data);
- }
-
- if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) {
- read_custom_data(schema.getArbGeomParams(), config, selector);
- }
-
- /* TODO: face sets */
-}
-
-DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
{
ISampleSelector sample_sel(time);
const ISubDSchema::Sample sample = m_schema.getValue(sample_sel);
@@ -1281,6 +1298,21 @@ DerivedMesh *AbcSubDReader::read_derivedmesh(DerivedMesh *dm, const float time,
settings.read_flag |= MOD_MESHSEQ_READ_ALL;
}
+ else {
+ /* If the face count changed (e.g. by triangulation), only read points.
+ * This prevents crash from T49813.
+ * TODO(kevin): perhaps find a better way to do this? */
+ if (face_counts->size() != dm->getNumPolys(dm) ||
+ face_indices->size() != dm->getNumLoops(dm))
+ {
+ settings.read_flag = MOD_MESHSEQ_READ_VERT;
+
+ if (err_str) {
+ *err_str = "Topology has changed, perhaps by triangulating the"
+ " mesh. Only vertices will be read!";
+ }
+ }
+ }
/* Only read point data when streaming meshes, unless we need to create new ones. */
CDStreamConfig config = get_config(new_dm ? new_dm : dm);
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 66e6585a3d3..64a3109232c 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -102,19 +102,13 @@ public:
void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
private:
void readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_start,
const Alembic::AbcGeom::ISampleSelector &sample_sel);
};
-void read_mesh_sample(ImportSettings *settings,
- const Alembic::AbcGeom::IPolyMeshSchema &schema,
- const Alembic::AbcGeom::ISampleSelector &selector,
- CDStreamConfig &config,
- bool &do_normals);
-
/* ************************************************************************** */
class AbcSubDReader : public AbcObjectReader {
@@ -128,14 +122,9 @@ public:
bool valid() const;
void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
};
-void read_subd_sample(ImportSettings *settings,
- const Alembic::AbcGeom::ISubDSchema &schema,
- const Alembic::AbcGeom::ISampleSelector &selector,
- CDStreamConfig &config);
-
/* ************************************************************************** */
void read_mverts(MVert *mverts,
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 314b2568bed..9dfccdb8c7f 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -170,13 +170,13 @@ static Imath::M44d blend_matrices(const Imath::M44d &m0, const Imath::M44d &m1,
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
- mat0[i][j] = m0[i][j];
+ mat0[i][j] = static_cast<float>(m0[i][j]);
}
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
- mat1[i][j] = m1[i][j];
+ mat1[i][j] = static_cast<float>(m1[i][j]);
}
}
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index 7ff927b4d33..0f733e67d3f 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -76,7 +76,7 @@ private:
/* ************************************************************************** */
-class CacheFile;
+struct CacheFile;
struct ImportSettings {
bool do_convert_mat;
@@ -165,10 +165,11 @@ public:
virtual void readObjectData(Main *bmain, float time) = 0;
- virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag)
+ virtual DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str)
{
(void)time;
(void)read_flag;
+ (void)err_str;
return dm;
}
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index 291a19bd2d5..6602c7e5a85 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -158,7 +158,7 @@ void AbcPointsReader::readObjectData(Main *bmain, float time)
Mesh *mesh = BKE_mesh_add(bmain, m_data_name.c_str());
DerivedMesh *dm = CDDM_from_mesh(mesh);
- DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0);
+ DerivedMesh *ndm = this->read_derivedmesh(dm, time, 0, NULL);
if (ndm != dm) {
dm->release(dm);
@@ -191,7 +191,8 @@ void read_points_sample(const IPointsSchema &schema,
N3fArraySamplePtr vnormals;
if (has_property(prop, "N")) {
- const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", time);
+ const Alembic::Util::uint32_t itime = static_cast<Alembic::Util::uint32_t>(time);
+ const IN3fArrayProperty &normals_prop = IN3fArrayProperty(prop, "N", itime);
if (normals_prop) {
vnormals = normals_prop.getValue(selector);
@@ -201,7 +202,7 @@ void read_points_sample(const IPointsSchema &schema,
read_mverts(config.mvert, positions, vnormals);
}
-DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/)
+DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char **/*err_str*/)
{
ISampleSelector sample_sel(time);
const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_points.h
index 0e69639ad8e..9864917f477 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_points.h
@@ -59,7 +59,7 @@ public:
void readObjectData(Main *bmain, float time);
- DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag);
+ DerivedMesh *read_derivedmesh(DerivedMesh *dm, const float time, int read_flag, const char **err_str);
};
void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index 7f8984f9970..e2fc7674c4e 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -92,8 +92,7 @@ void AbcTransformWriter::do_write()
/* Only apply rotation to root camera, parenting will propagate it. */
if (m_object->type == OB_CAMERA && !has_parent_camera(m_object)) {
float rot_mat[4][4];
- unit_m4(rot_mat);
- rotate_m4(rot_mat, 'X', -M_PI_2);
+ axis_angle_to_mat4_single(rot_mat, 'X', -M_PI_2);
mul_m4_m4m4(mat, mat, rot_mat);
}
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index f87d18605d4..f8ce72d845d 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -215,14 +215,13 @@ void convert_matrix(const Imath::M44d &xform, Object *ob,
{
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
- r_mat[i][j] = xform[i][j];
+ r_mat[i][j] = static_cast<float>(xform[i][j]);
}
}
if (ob->type == OB_CAMERA) {
float cam_to_yup[4][4];
- unit_m4(cam_to_yup);
- rotate_m4(cam_to_yup, 'X', M_PI_2);
+ axis_angle_to_mat4_single(cam_to_yup, 'X', M_PI_2);
mul_m4_m4m4(r_mat, r_mat, cam_to_yup);
}
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 2f423a9f8c5..60a96855d14 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -39,7 +39,7 @@ struct CacheReader {
using Alembic::Abc::chrono_t;
class AbcObjectReader;
-class ImportSettings;
+struct ImportSettings;
struct ID;
struct Object;
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index e690a255505..d8d017119b1 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -625,8 +625,8 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
CFRA = SFRA;
}
else if (min_time < max_time) {
- SFRA = min_time * FPS;
- EFRA = max_time * FPS;
+ SFRA = static_cast<int>(min_time * FPS);
+ EFRA = static_cast<int>(max_time * FPS);
CFRA = SFRA;
}
}
@@ -816,7 +816,7 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
- return abc_reader->read_derivedmesh(dm, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
}
else if (ISubD::matches(header)) {
if (ob->type != OB_MESH) {
@@ -824,7 +824,7 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
- return abc_reader->read_derivedmesh(dm, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
}
else if (IPoints::matches(header)) {
if (ob->type != OB_MESH) {
@@ -832,7 +832,7 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
- return abc_reader->read_derivedmesh(dm, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
}
else if (ICurves::matches(header)) {
if (ob->type != OB_CURVE) {
@@ -840,7 +840,7 @@ DerivedMesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
- return abc_reader->read_derivedmesh(dm, time, read_flag);
+ return abc_reader->read_derivedmesh(dm, time, read_flag, err_str);
}
*err_str = "Unsupported object type: verify object path"; // or poke developer
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index 00ea323f934..a67e903877a 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -73,7 +73,7 @@ struct AnimData *BKE_animdata_copy(struct AnimData *adt, const bool do_action);
bool BKE_animdata_copy_id(struct ID *id_to, struct ID *id_from, const bool do_action);
/* Copy AnimData Actions */
-void BKE_animdata_copy_id_action(struct ID *id);
+void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid);
/* Merge copies of data from source AnimData block */
typedef enum eAnimData_MergeCopy_Modes {
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index f3cfb901154..047d1787f76 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -120,7 +120,6 @@ void BKE_constraint_unique_name(struct bConstraint *con, struct ListBase *list);
void BKE_constraints_free(struct ListBase *list);
void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user);
void BKE_constraints_copy(struct ListBase *dst, const struct ListBase *src, bool do_extern);
-void BKE_constraints_relink(struct ListBase *list);
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, void *userdata);
void BKE_constraint_free_data(struct bConstraint *con);
void BKE_constraint_free_data_ex(struct bConstraint *con, bool do_id_user);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index 781b5edec30..bdd791f5645 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -80,6 +80,7 @@ void id_us_plus(struct ID *id);
void id_us_min(struct ID *id);
void id_fake_user_set(struct ID *id);
void id_fake_user_clear(struct ID *id);
+void BKE_id_clear_newpoin(struct ID *id);
void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local);
bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 2a1132df425..9bf4eba0f7a 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -307,17 +307,19 @@ bool BKE_animdata_copy_id(ID *id_to, ID *id_from, const bool do_action)
return true;
}
-void BKE_animdata_copy_id_action(ID *id)
+void BKE_animdata_copy_id_action(ID *id, const bool set_newid)
{
AnimData *adt = BKE_animdata_from_id(id);
if (adt) {
if (adt->action) {
id_us_min((ID *)adt->action);
- adt->action = BKE_action_copy(G.main, adt->action);
+ adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(G.main, adt->action)) :
+ BKE_action_copy(G.main, adt->action);
}
if (adt->tmpact) {
id_us_min((ID *)adt->tmpact);
- adt->tmpact = BKE_action_copy(G.main, adt->tmpact);
+ adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(G.main, adt->tmpact)) :
+ BKE_action_copy(G.main, adt->tmpact);
}
}
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 8ef1fae1155..0d509ecea06 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -249,6 +249,9 @@ void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local)
brush_new->id.us = 0;
+ /* setting newid is mandatory for complex make_lib_local logic... */
+ ID_NEW_SET(brush, brush_new);
+
if (!lib_local) {
BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 85ce399b770..9cb553aa27b 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -252,7 +252,7 @@ void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, cons
}
else if (rv3d->persp == RV3D_ORTHO) {
/* orthographic view */
- int sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
+ float sensor_size = BKE_camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y);
params->clipend *= 0.5f; // otherwise too extreme low zbuffer quality
params->clipsta = -params->clipend;
@@ -337,6 +337,8 @@ void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int win
viewplane.ymin *= pixsize;
viewplane.ymax *= pixsize;
+ /* Used for rendering (offset by near-clip with perspective views), passed to RE_SetPixelSize.
+ * For viewport drawing 'RegionView3D.pixsize'. */
params->viewdx = pixsize;
params->viewdy = params->ycor * pixsize;
params->viewplane = viewplane;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b85f1b838ff..9d4de30aa2c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -4705,27 +4705,6 @@ bConstraint *BKE_constraint_add_for_object(Object *ob, const char *name, short t
/* ......... */
-/* helper for BKE_constraints_relink() - call ID_NEW() on every ID reference the constraint has */
-static void con_relink_id_cb(bConstraint *UNUSED(con), ID **idpoin, bool UNUSED(is_reference), void *UNUSED(userdata))
-{
- /* ID_NEW() expects a struct with inline "id" member as first
- * since we've got the actual ID block, let's just inline this
- * code.
- *
- * See ID_NEW(a) in DNA_ID.h
- */
- if ((*idpoin) && (*idpoin)->newid)
- (*idpoin) = (void *)(*idpoin)->newid;
-}
-
-/* Reassign links that constraints have to other data (called during file loading?) */
-void BKE_constraints_relink(ListBase *conlist)
-{
- /* just a wrapper around ID-loop for just calling ID_NEW() on all ID refs */
- BKE_constraints_id_loop(conlist, con_relink_id_cb, NULL);
-}
-
-
/* Run the given callback on all ID-blocks in list of constraints */
void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *userdata)
{
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index d237de014fb..475afb9a571 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -1354,7 +1354,6 @@ static void scene_sort_groups(Main *bmain, Scene *sce)
/* test; are group objects all in this scene? */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
ob->id.tag &= ~LIB_TAG_DOIT;
- ob->id.newid = NULL; /* newid abuse for GroupObject */
}
for (base = sce->base.first; base; base = base->next)
base->object->id.tag |= LIB_TAG_DOIT;
@@ -1385,6 +1384,11 @@ static void scene_sort_groups(Main *bmain, Scene *sce)
group->gobject = listb;
}
}
+
+ /* newid abused for GroupObject, cleanup. */
+ for (ob = bmain->object.first; ob; ob = ob->id.next) {
+ ob->id.newid = NULL;
+ }
}
static void dag_scene_tag_rebuild(Scene *sce)
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 2242113b79b..cd2eac078cf 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -382,7 +382,8 @@ bGPDpalette *BKE_gpencil_palette_addnew(bGPdata *gpd, const char *name, bool set
sizeof(palette->info));
/* make this one the active one */
- if (setactive) {
+ /* NOTE: Always make this active if there's nothing else yet (T50123) */
+ if ((setactive) || (gpd->palettes.first == gpd->palettes.last)) {
BKE_gpencil_palette_setactive(gpd, palette);
}
@@ -1263,7 +1264,11 @@ void BKE_gpencil_palettecolor_changename(bGPdata *gpd, char *oldname, const char
bGPDlayer *gpl;
bGPDframe *gpf;
bGPDstroke *gps;
-
+
+ /* Sanity checks (gpd may not be set in the RNA pointers sometimes) */
+ if (ELEM(NULL, gpd, oldname, newname))
+ return;
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
for (gps = gpf->strokes.first; gps; gps = gps->next) {
@@ -1282,7 +1287,11 @@ void BKE_gpencil_palettecolor_delete_strokes(struct bGPdata *gpd, char *name)
bGPDlayer *gpl;
bGPDframe *gpf;
bGPDstroke *gps, *gpsn;
-
+
+ /* Sanity checks (gpd may not be set in the RNA pointers sometimes) */
+ if (ELEM(NULL, gpd, name))
+ return;
+
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
for (gps = gpf->strokes.first; gps; gps = gpsn) {
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index c9bad2160ff..a2d94ccc478 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -436,7 +436,6 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
Image *BKE_image_copy(Main *bmain, Image *ima)
{
Image *nima = image_alloc(bmain, ima->id.name + 2, ima->source, ima->type);
- ima->id.newid = &nima->id;
BLI_strncpy(nima->name, ima->name, sizeof(ima->name));
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 1c630624ec8..ff0112b4378 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -262,6 +262,14 @@ void id_fake_user_clear(ID *id)
}
}
+void BKE_id_clear_newpoin(ID *id)
+{
+ if (id->newid) {
+ id->newid->tag &= ~LIB_TAG_NEW;
+ }
+ id->newid = NULL;
+}
+
static int id_expand_local_callback(
void *UNUSED(user_data), struct ID *id_self, struct ID **id_pointer, int UNUSED(cd_flag))
{
@@ -325,6 +333,17 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
if (id_copy(bmain, id, &id_new, false)) {
id_new->us = 0;
+ /* setting newid is mandatory for complex make_lib_local logic... */
+ ID_NEW_SET(id, id_new);
+ Key *key = BKE_key_from_id(id), *key_new = BKE_key_from_id(id);
+ if (key && key_new) {
+ ID_NEW_SET(key, key_new);
+ }
+ bNodeTree *ntree = ntreeFromID(id), *ntree_new = ntreeFromID(id_new);
+ if (ntree && ntree_new) {
+ ID_NEW_SET(ntree, ntree_new);
+ }
+
if (!lib_local) {
BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
@@ -336,6 +355,8 @@ void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, c
/**
* Calls the appropriate make_local method for the block, unless test is set.
*
+ * \note Always set ID->newid pointer in case it gets duplicated...
+ *
* \param lib_local Special flag used when making a whole library's content local, it needs specific handling.
*
* \return true if the block can be made local.
@@ -554,6 +575,7 @@ bool id_copy(Main *bmain, ID *id, ID **newid, bool test)
return false;
}
+/** Does *not* set ID->newid pointer. */
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
ID *newid = NULL;
@@ -564,11 +586,11 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
if (RNA_property_editable(ptr, prop)) {
if (id_copy(CTX_data_main(C), id, &newid, false) && newid) {
/* copy animation actions too */
- BKE_animdata_copy_id_action(id);
+ BKE_animdata_copy_id_action(id, false);
/* us is 1 by convention, but RNA_property_pointer_set
* will also increment it, so set it to zero */
newid->us = 0;
-
+
/* assign copy */
RNA_id_pointer_create(newid, &idptr);
RNA_property_pointer_set(ptr, prop, idptr);
@@ -1104,9 +1126,6 @@ void *BKE_libblock_copy(Main *bmain, ID *id)
memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
}
-
- id->newid = idn;
- idn->tag |= LIB_TAG_NEW;
BKE_libblock_copy_data(idn, id, false);
@@ -1131,8 +1150,6 @@ void *BKE_libblock_copy_nolib(ID *id, const bool do_action)
memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID));
}
- id->newid = idn;
- idn->tag |= LIB_TAG_NEW;
idn->us = 1;
BKE_libblock_copy_data(idn, id, do_action);
@@ -1646,7 +1663,6 @@ void BKE_library_make_local(
const bool do_skip = (id && !BKE_idcode_is_linkable(GS(id->name)));
for (; id; id = id->next) {
- id->newid = NULL;
id->tag &= ~LIB_TAG_DOIT;
if (id->lib == NULL) {
@@ -1846,6 +1862,7 @@ void BKE_library_make_local(
}
}
+ BKE_main_id_clear_newpoins(bmain);
BLI_memarena_free(linklist_mem);
}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f7257b2b0dd..432adfaef53 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1052,6 +1052,9 @@ void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, con
ob_new->id.us = 0;
ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL;
+ /* setting newid is mandatory for complex make_lib_local logic... */
+ ID_NEW_SET(ob, ob_new);
+
if (!lib_local) {
BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE);
}
@@ -1184,7 +1187,10 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->type = target->type;
ob->data = target->data;
id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_TAG_EXTERN */
-
+
+ /* copy vertex groups */
+ defgroup_copy_list(&ob->defbase, &target->defbase);
+
/* copy material and index information */
ob->actcol = ob->totcol = 0;
if (ob->mat) MEM_freeN(ob->mat);
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 3ec174146b1..ef3b1559d5d 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -642,8 +642,7 @@ static void make_duplis_font(const DupliContext *ctx)
float rmat[4][4];
zero_v3(obmat[3]);
- unit_m4(rmat);
- rotate_m4(rmat, 'Z', -ct->rot);
+ axis_angle_to_mat4_single(rmat, 'Z', -ct->rot);
mul_m4_m4m4(obmat, obmat, rmat);
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 6923138b4b8..0b361d479f9 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -220,8 +220,8 @@ RigidBodyCon *BKE_rigidbody_copy_constraint(Object *ob)
/* preserve relationships between constraints and rigid bodies after duplication */
void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
{
- ID_NEW(rbc->ob1);
- ID_NEW(rbc->ob2);
+ ID_NEW_REMAP(rbc->ob1);
+ ID_NEW_REMAP(rbc->ob2);
}
/* ************************************** */
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index c7f406089d9..fa221348932 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -602,41 +602,41 @@ void set_sca_new_poins_ob(Object *ob)
if (act->flag & ACT_NEW) {
if (act->type==ACT_EDIT_OBJECT) {
bEditObjectActuator *eoa= act->data;
- ID_NEW(eoa->ob);
+ ID_NEW_REMAP(eoa->ob);
}
else if (act->type==ACT_SCENE) {
bSceneActuator *sca= act->data;
- ID_NEW(sca->camera);
+ ID_NEW_REMAP(sca->camera);
}
else if (act->type==ACT_CAMERA) {
bCameraActuator *ca= act->data;
- ID_NEW(ca->ob);
+ ID_NEW_REMAP(ca->ob);
}
else if (act->type==ACT_OBJECT) {
bObjectActuator *oa= act->data;
- ID_NEW(oa->reference);
+ ID_NEW_REMAP(oa->reference);
}
else if (act->type==ACT_MESSAGE) {
bMessageActuator *ma= act->data;
- ID_NEW(ma->toObject);
+ ID_NEW_REMAP(ma->toObject);
}
else if (act->type==ACT_PARENT) {
bParentActuator *para = act->data;
- ID_NEW(para->ob);
+ ID_NEW_REMAP(para->ob);
}
else if (act->type==ACT_ARMATURE) {
bArmatureActuator *aa = act->data;
- ID_NEW(aa->target);
- ID_NEW(aa->subtarget);
+ ID_NEW_REMAP(aa->target);
+ ID_NEW_REMAP(aa->subtarget);
}
else if (act->type==ACT_PROPERTY) {
bPropertyActuator *pa= act->data;
- ID_NEW(pa->ob);
+ ID_NEW_REMAP(pa->ob);
}
else if (act->type==ACT_STEERING) {
bSteeringActuator *sta = act->data;
- ID_NEW(sta->navmesh);
- ID_NEW(sta->target);
+ ID_NEW_REMAP(sta->navmesh);
+ ID_NEW_REMAP(sta->target);
}
}
act= act->next;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 125d6962332..fb6173cf771 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -186,8 +186,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
scen = BKE_libblock_copy(bmain, &sce->id);
BLI_duplicatelist(&(scen->base), &(sce->base));
- BKE_main_id_clear_newpoins(bmain);
-
id_us_plus((ID *)scen->world);
id_us_plus((ID *)scen->set);
/* id_us_plus((ID *)scen->gm.dome.warptext); */ /* XXX Not refcounted? see readfile.c */
@@ -225,7 +223,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
/* copy action and remove animation used by sequencer */
- BKE_animdata_copy_id_action(&scen->id);
+ BKE_animdata_copy_id_action(&scen->id, false);
if (type != SCE_COPY_FULL)
remove_sequencer_fcurves(scen);
@@ -317,7 +315,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
/* camera */
if (type == SCE_COPY_LINK_DATA || type == SCE_COPY_FULL) {
- ID_NEW(scen->camera);
+ ID_NEW_REMAP(scen->camera);
}
/* before scene copy */
@@ -328,7 +326,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
if (scen->world) {
id_us_plus((ID *)scen->world);
scen->world = BKE_world_copy(bmain, scen->world);
- BKE_animdata_copy_id_action((ID *)scen->world);
+ BKE_animdata_copy_id_action((ID *)scen->world, false);
}
if (sce->ed) {
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 65d751a8a72..1d2f5aee440 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -320,7 +320,8 @@ void BKE_sequencer_free_clipboard(void)
/* Manage pointers in the clipboard.
* note that these pointers should _never_ be access in the sequencer,
* they are only for storage while in the clipboard
- * notice 'newid' is used for temp pointer storage here, validate on access.
+ * notice 'newid' is used for temp pointer storage here, validate on access (this is safe usage,
+ * since those datablocks are fully out of Main lists).
*/
#define ID_PT (*id_pt)
static void seqclipboard_ptr_free(ID **id_pt)
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index b8949f9a0de..36b24fbb2dc 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -587,7 +587,7 @@ static void compensate_rotation_center(const int size, float aspect,
copy_v2_v2(intended_pivot, pivot);
copy_v2_v2(rotated_pivot, pivot);
- rotate_m2(rotation_mat, +angle);
+ angle_to_mat2(rotation_mat, +angle);
sub_v2_v2(rotated_pivot, origin);
mul_m2v2(rotation_mat, rotated_pivot);
mul_v2_fl(rotated_pivot, scale);
@@ -967,7 +967,7 @@ static void initialize_track_for_stabilization(StabContext *ctx,
pos[0] *= aspect;
angle = average_angle - atan2f(pos[1],pos[0]);
- rotate_m2(local_data->stabilization_rotation_base, angle);
+ angle_to_mat2(local_data->stabilization_rotation_base, angle);
/* Per track baseline value for zoom. */
len = len_v2(pos) + SCALE_ERROR_LIMIT_BIAS;
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index fc4bca12dac..029f6872b04 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -232,7 +232,6 @@ void mat4_to_size(float r[3], const float M[4][4]);
void translate_m4(float mat[4][4], float tx, float ty, float tz);
void rotate_m4(float mat[4][4], const char axis, const float angle);
-void rotate_m2(float mat[2][2], const float angle);
void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index 24c20ee7b50..d60be30e10d 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -122,8 +122,9 @@ void mat3_to_axis_angle(float axis[3], float *angle, float M[3][3]);
void mat4_to_axis_angle(float axis[3], float *angle, float M[4][4]);
void quat_to_axis_angle(float axis[3], float *angle, const float q[4]);
-void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle);
void angle_to_mat2(float R[2][2], const float angle);
+void axis_angle_to_mat3_single(float R[3][3], const char axis, const float angle);
+void axis_angle_to_mat4_single(float R[4][4], const char axis, const float angle);
void axis_angle_to_quat_single(float q[4], const char axis, const float angle);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index f31d0935b77..38947e139ff 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -3917,10 +3917,9 @@ void lookat_m4(float mat[4][4], float vx, float vy, float vz, float px, float py
float sine, cosine, hyp, hyp1, dx, dy, dz;
float mat1[4][4];
- unit_m4(mat);
unit_m4(mat1);
- rotate_m4(mat, 'Z', -twist);
+ axis_angle_to_mat4_single(mat, 'Z', -twist);
dx = px - vx;
dy = py - vy;
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index d95371b4ebc..50b92f5a383 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1681,53 +1681,47 @@ void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
}
/* TODO: enum for axis? */
+/**
+ * Rotate a matrix in-place.
+ *
+ * \note To create a new rotation matrix see:
+ * #axis_angle_to_mat4_single, #axis_angle_to_mat3_single, #angle_to_mat2
+ * (axis & angle args are compatible).
+ */
void rotate_m4(float mat[4][4], const char axis, const float angle)
{
- int col;
- float temp[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- float cosine, sine;
+ const float angle_cos = cosf(angle);
+ const float angle_sin = sinf(angle);
assert(axis >= 'X' && axis <= 'Z');
- cosine = cosf(angle);
- sine = sinf(angle);
switch (axis) {
case 'X':
- for (col = 0; col < 4; col++)
- temp[col] = cosine * mat[1][col] + sine * mat[2][col];
- for (col = 0; col < 4; col++) {
- mat[2][col] = -sine * mat[1][col] + cosine * mat[2][col];
- mat[1][col] = temp[col];
+ for (int col = 0; col < 4; col++) {
+ float temp = angle_cos * mat[1][col] + angle_sin * mat[2][col];
+ mat[2][col] = -angle_sin * mat[1][col] + angle_cos * mat[2][col];
+ mat[1][col] = temp;
}
break;
case 'Y':
- for (col = 0; col < 4; col++)
- temp[col] = cosine * mat[0][col] - sine * mat[2][col];
- for (col = 0; col < 4; col++) {
- mat[2][col] = sine * mat[0][col] + cosine * mat[2][col];
- mat[0][col] = temp[col];
+ for (int col = 0; col < 4; col++) {
+ float temp = angle_cos * mat[0][col] - angle_sin * mat[2][col];
+ mat[2][col] = angle_sin * mat[0][col] + angle_cos * mat[2][col];
+ mat[0][col] = temp;
}
break;
case 'Z':
- for (col = 0; col < 4; col++)
- temp[col] = cosine * mat[0][col] + sine * mat[1][col];
- for (col = 0; col < 4; col++) {
- mat[1][col] = -sine * mat[0][col] + cosine * mat[1][col];
- mat[0][col] = temp[col];
+ for (int col = 0; col < 4; col++) {
+ float temp = angle_cos * mat[0][col] + angle_sin * mat[1][col];
+ mat[1][col] = -angle_sin * mat[0][col] + angle_cos * mat[1][col];
+ mat[0][col] = temp;
}
break;
}
}
-void rotate_m2(float mat[2][2], const float angle)
-{
- mat[0][0] = mat[1][1] = cosf(angle);
- mat[0][1] = sinf(angle);
- mat[1][0] = -mat[0][1];
-}
-
/**
* Scale or rotate around a pivot point,
* a convenience function to avoid having to do inline.
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index b285a74b8ac..9b5dad3f767 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -1009,6 +1009,13 @@ void mat4_to_axis_angle(float axis[3], float *angle, float mat[4][4])
quat_to_axis_angle(axis, angle, q);
}
+void axis_angle_to_mat4_single(float mat[4][4], const char axis, const float angle)
+{
+ float mat3[3][3];
+ axis_angle_to_mat3_single(mat3, axis, angle);
+ copy_m4_m3(mat, mat3);
+}
+
/* rotation matrix from a single axis */
void axis_angle_to_mat3_single(float mat[3][3], const char axis, const float angle)
{
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 677c90051f7..cca9338e814 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -7706,6 +7706,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short
id->lib = main->curlib;
id->us = ID_FAKE_USERS(id);
id->icon_id = 0;
+ id->newid = NULL; /* Needed because .blend may have been saved with crap value here... */
/* this case cannot be direct_linked: it's just the ID part */
if (bhead->code == ID_ID) {
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index ae43c0a69d2..17334ca326c 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -169,6 +169,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
float angle;
mat4_to_loc_rot_size(loc, rot, size, mat);
mat3_to_vec_roll(rot, NULL, &angle);
+ bone->roll = angle;
}
copy_v3_v3(bone->head, mat[3]);
add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index 38855013ee1..e1a13559b08 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -33,11 +33,8 @@
UnitConverter::UnitConverter() : unit(), up_axis(COLLADAFW::FileInfo::Z_UP)
{
- unit_m4(x_up_mat4);
- rotate_m4(x_up_mat4, 'Y', -0.5 * M_PI);
-
- unit_m4(y_up_mat4);
- rotate_m4(y_up_mat4, 'X', 0.5 * M_PI);
+ axis_angle_to_mat4_single(x_up_mat4, 'Y', -0.5 * M_PI);
+ axis_angle_to_mat4_single(y_up_mat4, 'X', 0.5 * M_PI);
unit_m4(z_up_mat4);
unit_m4(scale_mat4);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index 8a0bec5ed1d..aedd00685b3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -48,6 +48,8 @@
#include "util/deg_util_foreach.h"
+#include <cstdio>
+
namespace DEG {
string deg_fcurve_id_name(const FCurve *fcu)
@@ -153,8 +155,8 @@ void deg_graph_build_finalize(Depsgraph *graph)
GHASH_FOREACH_END();
ID *id = id_node->id;
- if (id->tag & LIB_TAG_ID_RECALC_ALL &&
- id->tag & LIB_TAG_DOIT)
+ if ((id->tag & LIB_TAG_ID_RECALC_ALL) &&
+ (id->tag & LIB_TAG_DOIT))
{
id_node->tag_update(graph);
id->tag &= ~LIB_TAG_DOIT;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 3cf510eef25..13bcff405ca 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -370,19 +370,26 @@ SubgraphDepsNode *DepsgraphNodeBuilder::build_subgraph(Group *group)
void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
{
- if (ob->id.tag & LIB_TAG_DOIT) {
- IDDepsNode *id_node = m_graph->find_id_node(&ob->id);
- if (base != NULL) {
- id_node->layers |= base->lay;
- }
- return;
- }
- ob->id.tag |= LIB_TAG_DOIT;
-
- IDDepsNode *id_node = add_id_node(&ob->id);
+ const bool has_object = (ob->id.tag & LIB_TAG_DOIT);
+ IDDepsNode *id_node = (has_object)
+ ? m_graph->find_id_node(&ob->id)
+ : add_id_node(&ob->id);
+ /* Update node layers.
+ * Do it for both new and existing ID nodes. This is so because several
+ * bases might be sharing same object.
+ */
if (base != NULL) {
id_node->layers |= base->lay;
}
+ if (ob == scene->camera) {
+ /* Camera should always be updated, it used directly by viewport. */
+ id_node->layers |= (unsigned int)(-1);
+ }
+ /* Skip rest of components if the ID node was already there. */
+ if (has_object) {
+ return;
+ }
+ ob->id.tag |= LIB_TAG_DOIT;
ob->customdata_mask = 0;
/* Standard components. */
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 3502267d9ca..5604044e123 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -189,16 +189,23 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
/* Transforms props? */
if (prop) {
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
-
+ /* TODO(sergey): How to optimize this? */
if (strstr(prop_identifier, "location") ||
strstr(prop_identifier, "rotation") ||
- strstr(prop_identifier, "scale"))
+ strstr(prop_identifier, "scale") ||
+ strstr(prop_identifier, "matrix_"))
{
*type = DEPSNODE_TYPE_TRANSFORM;
return true;
}
+ else if (strstr(prop_identifier, "data")) {
+ /* We access object.data, most likely a geometry.
+ * Might be a bone tho..
+ */
+ *type = DEPSNODE_TYPE_GEOMETRY;
+ return true;
+ }
}
- // ...
}
else if (ptr->type == &RNA_ShapeKey) {
Key *key = (Key *)ptr->id.data;
@@ -371,8 +378,7 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
if (comp_node->type == DEPSNODE_TYPE_GEOMETRY) {
IDDepsNode *id_to = to->owner->owner;
IDDepsNode *id_from = from->owner->owner;
- Object *object_to = (Object *)id_to->id;
- if (id_to != id_from && (object_to->recalc & OB_RECALC_ALL)) {
+ if (id_to != id_from && (id_to->id->tag & LIB_TAG_ID_RECALC_ALL)) {
if ((id_from->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
id_from->tag_update(this);
id_from->eval_flags |= DAG_EVAL_NEED_CPU;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 12d837dfb29..15f65b394a9 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -96,7 +96,11 @@ static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op))
/* Just toggle editmode flag... */
gpd->flag ^= GP_DATA_STROKE_EDITMODE;
-
+ /* recalculate parent matrix */
+ if (gpd->flag & GP_DATA_STROKE_EDITMODE) {
+ ED_gpencil_reset_layers_parent(gpd);
+ }
+
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | ND_GPENCIL_EDITMODE, NULL);
WM_event_add_notifier(C, NC_SCENE | ND_MODE, NULL);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 564ba639983..76e85f20c36 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -915,7 +915,7 @@ void gp_subdivide_stroke(bGPDstroke *gps, const int new_totpoints)
/**
* Add randomness to stroke
* \param gps Stroke data
- * \param brsuh Brush data
+ * \param brush Brush data
*/
void gp_randomize_stroke(bGPDstroke *gps, bGPDbrush *brush)
{
@@ -997,6 +997,46 @@ void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4])
}
}
+/* reset parent matrix for all layers */
+void ED_gpencil_reset_layers_parent(bGPdata *gpd)
+{
+ bGPDspoint *pt;
+ int i;
+ float diff_mat[4][4];
+ float cur_mat[4][4];
+
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ if (gpl->parent != NULL) {
+ /* calculate new matrix */
+ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) {
+ invert_m4_m4(cur_mat, gpl->parent->obmat);
+ }
+ else if (gpl->partype == PARBONE) {
+ bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr);
+ if (pchan) {
+ float tmp_mat[4][4];
+ mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat);
+ invert_m4_m4(cur_mat, tmp_mat);
+ }
+ }
+
+ /* only redo if any change */
+ if (!equals_m4m4(gpl->inverse, cur_mat)) {
+ /* first apply current transformation to all strokes */
+ ED_gpencil_parent_location(gpl, diff_mat);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ mul_m4_v3(diff_mat, &pt->x);
+ }
+ }
+ }
+ /* set new parent matrix */
+ copy_m4_m4(gpl->inverse, cur_mat);
+ }
+ }
+ }
+}
/* ******************************************************** */
bool ED_gpencil_stroke_minmax(
const bGPDstroke *gps, const bool use_select,
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index bc93b5622cb..74d9ad0886d 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -185,6 +185,8 @@ int ED_undo_gpencil_step(struct bContext *C, int step, const char *name);
/* get difference matrix using parent */
void ED_gpencil_parent_location(struct bGPDlayer *gpl, float diff_mat[4][4]);
+/* reset parent matrix for all layers */
+void ED_gpencil_reset_layers_parent(struct bGPdata *gpd);
#endif /* __ED_GPENCIL_H__ */
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index e016e014a1a..8579778ff79 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -1005,15 +1005,6 @@ DEF_ICON(MATCAP_23)
DEF_ICON(MATCAP_24)
/* vector icons, VICO_ prefix added */
-DEF_VICO(VIEW3D_VEC)
-DEF_VICO(EDIT_VEC)
-DEF_VICO(EDITMODE_VEC_DEHLT)
-DEF_VICO(EDITMODE_VEC_HLT)
-DEF_VICO(DISCLOSURE_TRI_RIGHT_VEC)
-DEF_VICO(DISCLOSURE_TRI_DOWN_VEC)
-DEF_VICO(MOVE_UP_VEC)
-DEF_VICO(MOVE_DOWN_VEC)
-DEF_VICO(X_VEC)
DEF_VICO(SMALL_TRI_RIGHT_VEC)
DEF_VICO(KEYTYPE_KEYFRAME_VEC)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index d1f14bf5c1a..d48cfbee413 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -181,7 +181,7 @@ enum {
UI_BUT_HAS_SEP_CHAR = (1 << 27), /* but->str contains UI_SEP_CHAR, used for key shortcuts */
UI_BUT_UPDATE_DELAY = (1 << 28), /* don't run updates while dragging (needed in rare cases). */
UI_BUT_TEXTEDIT_UPDATE = (1 << 29), /* when widget is in textedit mode, update value on each char stroke */
- UI_BUT_SEARCH_UNLINK = (1 << 30), /* show unlink for search button */
+ UI_BUT_VALUE_CLEAR = (1 << 30), /* show 'x' icon to clear/unlink value of text or search button */
};
#define UI_PANEL_WIDTH 340
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 6bba35e821f..a913421d12c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -1987,22 +1987,29 @@ uiBut *ui_but_drag_multi_edit_get(uiBut *but)
/** \name Check to show extra icons
*
* Extra icons are shown on the right hand side of buttons.
+ * This could (should!) definitely become more generic, but for now this is good enough.
* \{ */
+static bool ui_but_icon_extra_is_visible_text_clear(const uiBut *but)
+{
+ BLI_assert(but->type == UI_BTYPE_TEXT);
+ return ((but->flag & UI_BUT_VALUE_CLEAR) && but->drawstr && but->drawstr[0]);
+}
+
static bool ui_but_icon_extra_is_visible_search_unlink(const uiBut *but)
{
BLI_assert(but->type == UI_BTYPE_SEARCH_MENU);
return ((but->editstr == NULL) &&
(but->drawstr[0] != '\0') &&
- (but->flag & UI_BUT_SEARCH_UNLINK));
+ (but->flag & UI_BUT_VALUE_CLEAR));
}
-static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
+static bool ui_but_icon_extra_is_visible_search_eyedropper(uiBut *but)
{
StructRNA *type;
short idcode;
- BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_SEARCH_UNLINK));
+ BLI_assert(but->type == UI_BTYPE_SEARCH_MENU && (but->flag & UI_BUT_VALUE_CLEAR));
if (but->rnaprop == NULL) {
return false;
@@ -2011,21 +2018,31 @@ static bool ui_but_icon_extra_is_visible_eyedropper(uiBut *but)
type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
idcode = RNA_type_to_ID_code(type);
-
return ((but->editstr == NULL) &&
(idcode == ID_OB || OB_DATA_SUPPORT_ID(idcode)));
}
uiButExtraIconType ui_but_icon_extra_get(uiBut *but)
{
- if ((but->flag & UI_BUT_SEARCH_UNLINK) == 0) {
- /* pass */
- }
- else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
- return UI_BUT_ICONEXTRA_UNLINK;
- }
- else if (ui_but_icon_extra_is_visible_eyedropper(but)) {
- return UI_BUT_ICONEXTRA_EYEDROPPER;
+ switch (but->type) {
+ case UI_BTYPE_TEXT:
+ if (ui_but_icon_extra_is_visible_text_clear(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ break;
+ case UI_BTYPE_SEARCH_MENU:
+ if ((but->flag & UI_BUT_VALUE_CLEAR) == 0) {
+ /* pass */
+ }
+ else if (ui_but_icon_extra_is_visible_search_unlink(but)) {
+ return UI_BUT_ICONEXTRA_CLEAR;
+ }
+ else if (ui_but_icon_extra_is_visible_search_eyedropper(but)) {
+ return UI_BUT_ICONEXTRA_EYEDROPPER;
+ }
+ break;
+ default:
+ break;
}
return UI_BUT_ICONEXTRA_NONE;
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index 9c808589d26..6efa711a53f 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -748,7 +748,7 @@ static int datadropper_poll(bContext *C)
if ((CTX_wm_window(C) != NULL) &&
(but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
(but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_SEARCH_UNLINK))
+ (but->flag & UI_BUT_VALUE_CLEAR))
{
if (prop && RNA_property_type(prop) == PROP_POINTER) {
StructRNA *type = RNA_property_pointer_type(&ptr, prop);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 09ba666773b..ce67c24f096 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -2554,6 +2554,18 @@ void ui_but_text_password_hide(char password_str[UI_MAX_PASSWORD_STR], uiBut *bu
}
}
+static void ui_but_text_clear(bContext *C, uiBut *but, uiHandleButtonData *data)
+{
+ /* most likely NULL, but let's check, and give it temp zero string */
+ if (!data->str) {
+ data->str = MEM_callocN(1, "temp str");
+ }
+ data->str[0] = 0;
+
+ ui_apply_but_TEX(C, but, data);
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+}
+
/* ************* in-button text selection/editing ************* */
@@ -3820,6 +3832,21 @@ static int ui_do_but_KEYEVT(
return WM_UI_HANDLER_CONTINUE;
}
+static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
+{
+ int x = mouse_xy[0], y = mouse_xy[1];
+ rcti icon_rect;
+
+ BLI_assert(ui_but_icon_extra_get(but) != UI_BUT_ICONEXTRA_NONE);
+
+ ui_window_to_block(region, but->block, &x, &y);
+
+ BLI_rcti_rctf_copy(&icon_rect, &but->rect);
+ icon_rect.xmin = icon_rect.xmax - (BLI_rcti_size_y(&icon_rect));
+
+ return BLI_rcti_isect_pt(&icon_rect, x, y);
+}
+
static int ui_do_but_TEX(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
@@ -3833,7 +3860,14 @@ static int ui_do_but_TEX(
/* pass */
}
else {
- button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ const bool has_icon_extra = ui_but_icon_extra_get(but) == UI_BUT_ICONEXTRA_CLEAR;
+
+ if (has_icon_extra && ui_but_is_mouse_over_icon_extra(data->region, but, &event->x)) {
+ ui_but_text_clear(C, but, data);
+ }
+ else {
+ button_activate_state(C, but, BUTTON_STATE_TEXT_EDITING);
+ }
return WM_UI_HANDLER_BREAK;
}
}
@@ -3854,47 +3888,29 @@ static int ui_do_but_SEARCH_UNLINK(
bContext *C, uiBlock *block, uiBut *but,
uiHandleButtonData *data, const wmEvent *event)
{
- uiButExtraIconType extra_icon_type;
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
+ const bool has_icon_extra = (extra_icon_type != UI_BUT_ICONEXTRA_NONE);
/* unlink icon is on right */
if ((ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY)) &&
- ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
+ (has_icon_extra == true) &&
+ (ui_but_is_mouse_over_icon_extra(data->region, but, &event->x) == true))
{
- ARegion *ar = data->region;
- rcti rect;
- int x = event->x, y = event->y;
-
- ui_window_to_block(ar, but->block, &x, &y);
-
- BLI_rcti_rctf_copy(&rect, &but->rect);
-
- rect.xmin = rect.xmax - (BLI_rcti_size_y(&rect));
- /* handle click on unlink/eyedropper icon */
- if (BLI_rcti_isect_pt(&rect, x, y)) {
- /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
- if (event->val == KM_RELEASE) {
- /* unlink */
- if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
- /* most likely NULL, but let's check, and give it temp zero string */
- if (data->str == NULL) {
- data->str = MEM_callocN(1, "temp str");
- }
- data->str[0] = 0;
-
- ui_apply_but_TEX(C, but, data);
- button_activate_state(C, but, BUTTON_STATE_EXIT);
- }
- /* eyedropper */
- else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
- WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
- }
- else {
- BLI_assert(0);
- }
+ /* doing this on KM_PRESS calls eyedropper after clicking unlink icon */
+ if (event->val == KM_RELEASE) {
+ /* unlink */
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
+ ui_but_text_clear(C, but, data);
+ }
+ /* eyedropper */
+ else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
+ WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+ }
+ else {
+ BLI_assert(0);
}
-
- return WM_UI_HANDLER_BREAK;
}
+ return WM_UI_HANDLER_BREAK;
}
return ui_do_but_TEX(C, block, but, data, event);
}
@@ -7069,7 +7085,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_TEXT:
case UI_BTYPE_SEARCH_MENU:
if ((but->type == UI_BTYPE_SEARCH_MENU) &&
- (but->flag & UI_BUT_SEARCH_UNLINK))
+ (but->flag & UI_BUT_VALUE_CLEAR))
{
retval = ui_do_but_SEARCH_UNLINK(C, block, but, data, event);
if (retval & WM_UI_HANDLER_BREAK) {
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 0f9db6fd9b6..7529f60c6f0 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -127,7 +127,7 @@ enum {
* (e.g. 'x' icon in search menu) - used with ui_but_icon_extra_get */
typedef enum uiButExtraIconType {
UI_BUT_ICONEXTRA_NONE = 1,
- UI_BUT_ICONEXTRA_UNLINK,
+ UI_BUT_ICONEXTRA_CLEAR,
UI_BUT_ICONEXTRA_EYEDROPPER,
} uiButExtraIconType;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 875522e01c6..b128bf47b5f 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1659,7 +1659,7 @@ void ui_but_add_search(uiBut *but, PointerRNA *ptr, PropertyRNA *prop, PointerRN
but->rnasearchprop = searchprop;
but->drawflag |= UI_BUT_ICON_LEFT | UI_BUT_TEXT_LEFT;
if (RNA_property_is_unlink(prop)) {
- but->flag |= UI_BUT_SEARCH_UNLINK;
+ but->flag |= UI_BUT_VALUE_CLEAR;
}
if (RNA_property_type(prop) == PROP_ENUM) {
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index cdf34642a8d..466978272bc 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -851,7 +851,7 @@ static void ui_searchbox_select(bContext *C, ARegion *ar, uiBut *but, int step)
}
else {
/* only let users step into an 'unset' state for unlink buttons */
- data->active = (but->flag & UI_BUT_SEARCH_UNLINK) ? -1 : 0;
+ data->active = (but->flag & UI_BUT_VALUE_CLEAR) ? -1 : 0;
}
}
@@ -922,8 +922,8 @@ bool ui_searchbox_apply(uiBut *but, ARegion *ar)
return true;
}
- else if (but->flag & UI_BUT_SEARCH_UNLINK) {
- /* It is valid for _UNLINK flavor to have no active element (it's a valid way to unlink). */
+ else if (but->flag & UI_BUT_VALUE_CLEAR) {
+ /* It is valid for _VALUE_CLEAR flavor to have no active element (it's a valid way to unlink). */
but->editstr[0] = '\0';
return true;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 09c5854fb26..80784e86b1e 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -302,7 +302,10 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_LOCAL:
if (id) {
- if (id_make_local(CTX_data_main(C), id, false, false)) {
+ Main *bmain = CTX_data_main(C);
+ if (id_make_local(bmain, id, false, false)) {
+ BKE_main_id_clear_newpoins(bmain);
+
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template->ptr, template->prop);
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 1d51c0588b6..8dfbbdd02eb 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -119,6 +119,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
else
but = uiDefButR_prop(block, UI_BTYPE_TEXT, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL);
+ PropertySubType subtype = RNA_property_subtype(prop);
+ if (!(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME) || (block->flag & UI_BLOCK_LIST_ITEM))) {
+ UI_but_flag_enable(but, UI_BUT_VALUE_CLEAR);
+ }
if (RNA_property_flag(prop) & PROP_TEXTEDIT_UPDATE) {
UI_but_flag_enable(but, UI_BUT_TEXTEDIT_UPDATE);
}
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 6cb3aa19db3..b75ecf68136 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -1513,10 +1513,10 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
/* draws text and icons for buttons */
static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *but, rcti *rect)
{
+ const uiButExtraIconType extra_icon_type = ui_but_icon_extra_get(but);
const bool show_menu_icon = ui_but_draw_menu_icon(but);
float alpha = (float)wcol->text[3] / 255.0f;
char password_str[UI_MAX_DRAW_STR];
- uiButExtraIconType extra_icon_type;
ui_but_text_password_hide(password_str, but, false);
@@ -1582,15 +1582,13 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
rect->xmax -= (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
- /* unlink icon for this button type */
- if ((but->type == UI_BTYPE_SEARCH_MENU) &&
- ((extra_icon_type = ui_but_icon_extra_get(but)) != UI_BUT_ICONEXTRA_NONE))
- {
+ /* extra icons, e.g. 'x' icon to clear text or icon for eyedropper */
+ if (extra_icon_type != UI_BUT_ICONEXTRA_NONE) {
rcti temp = *rect;
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
- if (extra_icon_type == UI_BUT_ICONEXTRA_UNLINK) {
+ if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
widget_draw_icon(but, ICON_X, alpha, &temp, false);
}
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index a84b8d9dcc8..44453d03ade 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2140,7 +2140,7 @@ static float snap_v2_angle(float r[2], const float v[2], const float v_ref[2], f
normalize_v2_v2(v_unit, v);
angle = angle_signed_v2v2(v_unit, v_ref);
angle_delta = (roundf(angle / angle_snap) * angle_snap) - angle;
- rotate_m2(m2, angle_delta);
+ angle_to_mat2(m2, angle_delta);
mul_v2_m2v2(r, m2, v);
return angle + angle_delta;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 6e973740f7c..a6f7388cb49 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -1252,10 +1252,10 @@ static void copy_object_set_idnew(bContext *C)
/********************* Make Duplicates Real ************************/
/**
- * \note regarding hashing dupli-objects, skip the first member of #DupliObject.persistent_id
+ * \note regarding hashing dupli-objects when using OB_DUPLIGROUP, skip the first member of #DupliObject.persistent_id
* since its a unique index and we only want to know if the group objects are from the same dupli-group instance.
*/
-static unsigned int dupliobject_hash(const void *ptr)
+static unsigned int dupliobject_group_hash(const void *ptr)
{
const DupliObject *dob = ptr;
unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
@@ -1266,7 +1266,20 @@ static unsigned int dupliobject_hash(const void *ptr)
return hash;
}
-static bool dupliobject_cmp(const void *a_, const void *b_)
+/**
+ * \note regarding hashing dupli-objects when NOT using OB_DUPLIGROUP, include the first member of #DupliObject.persistent_id
+ * since its the index of the vertex/face the object is instantiated on and we want to identify objects on the same vertex/face.
+ */
+static unsigned int dupliobject_hash(const void *ptr)
+{
+ const DupliObject *dob = ptr;
+ unsigned int hash = BLI_ghashutil_ptrhash(dob->ob);
+ hash ^= (dob->persistent_id[0] ^ 0);
+ return hash;
+}
+
+/* Compare function that matches dupliobject_group_hash */
+static bool dupliobject_group_cmp(const void *a_, const void *b_)
{
const DupliObject *a = a_;
const DupliObject *b = b_;
@@ -1289,6 +1302,24 @@ static bool dupliobject_cmp(const void *a_, const void *b_)
return false;
}
+/* Compare function that matches dupliobject_hash */
+static bool dupliobject_cmp(const void *a_, const void *b_)
+{
+ const DupliObject *a = a_;
+ const DupliObject *b = b_;
+
+ if (a->ob != b->ob) {
+ return true;
+ }
+
+ if (a->persistent_id[0] != b->persistent_id[0]) {
+ return true;
+ }
+
+ /* matching */
+ return false;
+}
+
static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
const bool use_base_parent,
const bool use_hierarchy)
@@ -1307,13 +1338,18 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new(__func__);
if (use_hierarchy) {
- parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ if (base->object->transflag & OB_DUPLIGROUP) {
+ parent_gh = BLI_ghash_new(dupliobject_group_hash, dupliobject_group_cmp, __func__);
+ }
+ else {
+ parent_gh = BLI_ghash_new(dupliobject_hash, dupliobject_cmp, __func__);
+ }
}
}
for (dob = lb->first; dob; dob = dob->next) {
Base *basen;
- Object *ob = BKE_object_copy(bmain, dob->ob);
+ Object *ob = ID_NEW_SET(dob->ob, BKE_object_copy(bmain, dob->ob));
/* font duplis can have a totcol without material, we get them from parent
* should be implemented better...
@@ -1357,6 +1393,11 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
}
}
+ /* Remap new object to itself, and clear again newid pointer of orig object. */
+ BKE_libblock_relink(&ob->id);
+ set_sca_new_poins_ob(ob);
+ BKE_id_clear_newpoin(&dob->ob->id);
+
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
@@ -1375,9 +1416,14 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
* they won't be read, this is simply for a hash lookup. */
DupliObject dob_key;
dob_key.ob = ob_src_par;
- memcpy(&dob_key.persistent_id[1],
- &dob->persistent_id[1],
- sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ if (base->object->transflag & OB_DUPLIGROUP) {
+ memcpy(&dob_key.persistent_id[1],
+ &dob->persistent_id[1],
+ sizeof(dob->persistent_id[1]) * (MAX_DUPLI_RECUR - 1));
+ }
+ else {
+ dob_key.persistent_id[0] = dob->persistent_id[0];
+ }
ob_dst_par = BLI_ghash_lookup(parent_gh, &dob_key);
}
@@ -1442,8 +1488,6 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (parent_gh)
BLI_ghash_free(parent_gh, NULL, NULL);
- copy_object_set_idnew(C);
-
free_object_duplilist(lb);
base->object->transflag &= ~OB_DUPLI;
@@ -1918,8 +1962,12 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
+/* Does set ID->newid pointers. */
static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base, int dupflag)
{
+#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
+#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
+
Base *basen = NULL;
Material ***matarar;
Object *ob, *obn;
@@ -1931,7 +1979,7 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
; /* nothing? */
}
else {
- obn = BKE_object_copy(bmain, ob);
+ obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
DAG_id_tag_update(&obn->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
basen = MEM_mallocN(sizeof(Base), "duplibase");
@@ -1953,20 +2001,21 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
/* duplicates using userflags */
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->id);
+ BKE_animdata_copy_id_action(&obn->id, true);
}
if (dupflag & USER_DUP_MAT) {
for (a = 0; a < obn->totcol; a++) {
id = (ID *)obn->mat[a];
if (id) {
- ID_NEW_US(obn->mat[a])
- else
- obn->mat[a] = BKE_material_copy(bmain, obn->mat[a]);
+ ID_NEW_REMAP_US(obn->mat[a])
+ else {
+ obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a]));
+ }
id_us_min(id);
if (dupflag & USER_DUP_ACT) {
- BKE_animdata_copy_id_action(&obn->mat[a]->id);
+ BKE_animdata_copy_id_action(&obn->mat[a]->id, true);
}
}
}
@@ -1978,9 +2027,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
switch (obn->type) {
case OB_MESH:
if (dupflag & USER_DUP_MESH) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_mesh_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -1988,9 +2037,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_CURVE:
if (dupflag & USER_DUP_CURVE) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -1998,9 +2047,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_SURF:
if (dupflag & USER_DUP_SURF) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2008,9 +2057,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_FONT:
if (dupflag & USER_DUP_FONT) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_curve_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2018,9 +2067,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_MBALL:
if (dupflag & USER_DUP_MBALL) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_mball_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2028,9 +2077,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_LAMP:
if (dupflag & USER_DUP_LAMP) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_lamp_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_lamp_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2041,9 +2090,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (obn->pose)
BKE_pose_tag_recalc(bmain, obn->pose);
if (dupflag & USER_DUP_ARM) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_armature_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data));
BKE_pose_rebuild(obn, obn->data);
didit = 1;
}
@@ -2052,9 +2101,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_LATTICE:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_lattice_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2062,9 +2111,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_CAMERA:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_camera_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2072,9 +2121,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
break;
case OB_SPEAKER:
if (dupflag != 0) {
- ID_NEW_US2(obn->data)
+ ID_NEW_REMAP_US2(obn->data)
else {
- obn->data = BKE_speaker_copy(bmain, obn->data);
+ obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data));
didit = 1;
}
id_us_min(id);
@@ -2089,12 +2138,15 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
if (dupflag & USER_DUP_ACT) {
bActuator *act;
- BKE_animdata_copy_id_action((ID *)obn->data);
+ BKE_animdata_copy_id_action((ID *)obn->data, true);
if (key) {
- BKE_animdata_copy_id_action((ID *)key);
+ BKE_animdata_copy_id_action((ID *)key, true);
}
/* Update the duplicated action in the action actuators */
+ /* XXX TODO this code is all wrong! actact->act is user-refcounted (see readfile.c),
+ * and what about other ID pointers of other BGE logic bricks,
+ * and since this is object-level, why is it only ran if obdata was duplicated??? -mont29 */
for (act = obn->actuators.first; act; act = act->next) {
if (act->type == ACT_ACTION) {
bActionActuator *actact = (bActionActuator *) act->data;
@@ -2111,9 +2163,10 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
for (a = 0; a < obn->totcol; a++) {
id = (ID *)(*matarar)[a];
if (id) {
- ID_NEW_US((*matarar)[a])
- else
- (*matarar)[a] = BKE_material_copy(bmain, (*matarar)[a]);
+ ID_NEW_REMAP_US((*matarar)[a])
+ else {
+ (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a]));
+ }
id_us_min(id);
}
}
@@ -2122,6 +2175,9 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base
}
}
return basen;
+
+#undef ID_NEW_REMAP_US
+#undef ID_NEW_REMAP_US2
}
/* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */
@@ -2134,8 +2190,7 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
Base *basen;
Object *ob;
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
if (basen == NULL) {
@@ -2154,6 +2209,8 @@ Base *ED_object_add_duplicate(Main *bmain, Scene *scene, Base *base, int dupflag
ED_render_id_flush_update(bmain, ob->data);
}
+ BKE_main_id_clear_newpoins(bmain);
+
return basen;
}
@@ -2165,8 +2222,7 @@ static int duplicate_exec(bContext *C, wmOperator *op)
const bool linked = RNA_boolean_get(op->ptr, "linked");
int dupflag = (linked) ? 0 : U.dupflag;
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
CTX_DATA_BEGIN (C, Base *, base, selected_bases)
{
@@ -2192,6 +2248,8 @@ static int duplicate_exec(bContext *C, wmOperator *op)
copy_object_set_idnew(C);
+ BKE_main_id_clear_newpoins(bmain);
+
DAG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
@@ -2250,8 +2308,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
base->flag = ob->flag;
/* prepare dupli */
- BKE_main_id_clear_newpoins(bmain);
- clear_sca_new_poins(); /* sensor/contr/act */
+ clear_sca_new_poins(); /* BGE logic */
basen = object_add_duplicate_internal(bmain, scene, base, dupflag);
@@ -2277,6 +2334,8 @@ static int add_named_exec(bContext *C, wmOperator *op)
copy_object_set_idnew(C);
+ BKE_main_id_clear_newpoins(bmain);
+
DAG_relations_tag_update(bmain);
MEM_freeN(base);
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a3ff8dcb676..0bfd4b054eb 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1730,6 +1730,7 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
/**************************** Make Single User ********************************/
+/* Warning, sets ID->newid pointers of objects and groups, but does not clear them. */
static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups)
{
Base *base;
@@ -1737,18 +1738,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
Group *group, *groupn;
GroupObject *go;
- clear_sca_new_poins(); /* sensor/contr/act */
-
- /* newid may still have some trash from Outliner tree building, so clear that first to avoid errors, see T26002.
- * We have to clear whole datablocks, not only Object one may be accessed here, see T49905. */
- ListBase *lbarray[MAX_LIBARRAY];
- int a = set_listbasepointers(bmain, lbarray);
- while (a--) {
- ListBase *lb = lbarray[a];
- for (ID *id = lb->first; id; id = id->next) {
- id->newid = NULL;
- }
- }
+ clear_sca_new_poins(); /* BGE logic */
/* duplicate (must set newid) */
for (base = FIRSTBASE; base; base = base->next) {
@@ -1757,8 +1747,7 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
if ((base->flag & flag) == flag) {
if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) {
/* base gets copy of object */
- obn = BKE_object_copy(bmain, ob);
- base->object = obn;
+ base->object = obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob));
if (copy_groups) {
if (ob->flag & OB_FROMGROUP) {
@@ -1788,8 +1777,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* duplicate groups that consist entirely of duplicated objects */
for (group = bmain->group.first; group; group = group->id.next) {
- group->id.newid = NULL;
-
if (copy_groups && group->gobject.first) {
bool all_duplicated = true;
@@ -1801,10 +1788,11 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
}
if (all_duplicated) {
- groupn = BKE_group_copy(bmain, group);
+ groupn = ID_NEW_SET(group, BKE_group_copy(bmain, group));
- for (go = groupn->gobject.first; go; go = go->next)
+ for (go = groupn->gobject.first; go; go = go->next) {
go->ob = (Object *)go->ob->id.newid;
+ }
}
}
}
@@ -1812,8 +1800,8 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
/* group pointers in scene */
BKE_scene_groups_relink(scene);
- ID_NEW(scene->camera);
- if (v3d) ID_NEW(v3d->camera);
+ ID_NEW_REMAP(scene->camera);
+ if (v3d) ID_NEW_REMAP(v3d->camera);
/* object and group pointers */
for (base = FIRSTBASE; base; base = base->next) {
@@ -1836,6 +1824,8 @@ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
}
single_object_users(bmain, scene, NULL, OB_DONE, copy_groups);
+
+ BKE_main_id_clear_newpoins(bmain);
}
static void new_id_matar(Main *bmain, Material **matar, const int totcol)
@@ -1852,9 +1842,8 @@ static void new_id_matar(Main *bmain, Material **matar, const int totcol)
id_us_min(id);
}
else if (id->us > 1) {
- matar[a] = BKE_material_copy(bmain, matar[a]);
+ matar[a] = ID_NEW_SET(id, BKE_material_copy(bmain, matar[a]));
id_us_min(id);
- id->newid = (ID *)matar[a];
}
}
}
@@ -1882,45 +1871,46 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
switch (ob->type) {
case OB_LAMP:
- ob->data = la = BKE_lamp_copy(bmain, ob->data);
+ ob->data = la = ID_NEW_SET(ob->data, BKE_lamp_copy(bmain, ob->data));
for (a = 0; a < MAX_MTEX; a++) {
if (la->mtex[a]) {
- ID_NEW(la->mtex[a]->object);
+ ID_NEW_REMAP(la->mtex[a]->object);
}
}
break;
case OB_CAMERA:
- ob->data = BKE_camera_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_camera_copy(bmain, ob->data));
break;
case OB_MESH:
- ob->data = me = BKE_mesh_copy(bmain, ob->data);
- if (me->key)
- BKE_animdata_copy_id_action((ID *)me->key);
+ /* Needed to remap texcomesh below. */
+ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data));
+ if (me->key) /* We do not need to set me->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)me->key, false);
break;
case OB_MBALL:
- ob->data = BKE_mball_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_mball_copy(bmain, ob->data));
break;
case OB_CURVE:
case OB_SURF:
case OB_FONT:
- ob->data = cu = BKE_curve_copy(bmain, ob->data);
- ID_NEW(cu->bevobj);
- ID_NEW(cu->taperobj);
- if (cu->key)
- BKE_animdata_copy_id_action((ID *)cu->key);
+ ob->data = cu = ID_NEW_SET(ob->data, BKE_curve_copy(bmain, ob->data));
+ ID_NEW_REMAP(cu->bevobj);
+ ID_NEW_REMAP(cu->taperobj);
+ if (cu->key) /* We do not need to set cu->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)cu->key, false);
break;
case OB_LATTICE:
- ob->data = lat = BKE_lattice_copy(bmain, ob->data);
- if (lat->key)
- BKE_animdata_copy_id_action((ID *)lat->key);
+ ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data));
+ if (lat->key) /* We do not need to set lat->key->id.newid here... */
+ BKE_animdata_copy_id_action((ID *)lat->key, false);
break;
case OB_ARMATURE:
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- ob->data = BKE_armature_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_armature_copy(bmain, ob->data));
BKE_pose_rebuild(ob, ob->data);
break;
case OB_SPEAKER:
- ob->data = BKE_speaker_copy(bmain, ob->data);
+ ob->data = ID_NEW_SET(ob->data, BKE_speaker_copy(bmain, ob->data));
break;
default:
if (G.debug & G_DEBUG)
@@ -1933,17 +1923,16 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
* AnimData structure, which is not what we want.
* (sergey)
*/
- BKE_animdata_copy_id_action((ID *)ob->data);
+ BKE_animdata_copy_id_action((ID *)ob->data, false);
id_us_min(id);
- id->newid = ob->data;
}
}
}
me = bmain->mesh.first;
while (me) {
- ID_NEW(me->texcomesh);
+ ID_NEW_REMAP(me->texcomesh);
me = me->id.next;
}
}
@@ -1957,7 +1946,7 @@ static void single_object_action_users(Scene *scene, const int flag)
ob = base->object;
if (!ID_IS_LINKED_DATABLOCK(ob) && (flag == 0 || (base->flag & SELECT)) ) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
- BKE_animdata_copy_id_action(&ob->id);
+ BKE_animdata_copy_id_action(&ob->id, false);
}
}
}
@@ -1976,11 +1965,11 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
for (a = 1; a <= ob->totcol; a++) {
ma = give_current_material(ob, a);
if (ma) {
- /* do not test for LIB_TAG_NEW: this functions guaranteed delivers single_users! */
+ /* do not test for LIB_TAG_NEW or use newid: this functions guaranteed delivers single_users! */
if (ma->id.us > 1) {
man = BKE_material_copy(bmain, ma);
- BKE_animdata_copy_id_action(&man->id);
+ BKE_animdata_copy_id_action(&man->id, false);
man->id.us = 0;
assign_material(ob, man, a, BKE_MAT_ASSIGN_USERPREF);
@@ -1991,7 +1980,7 @@ static void single_mat_users(Main *bmain, Scene *scene, const int flag, const bo
if (tex->id.us > 1) {
id_us_min(&tex->id);
tex = BKE_texture_copy(bmain, tex);
- BKE_animdata_copy_id_action(&tex->id);
+ BKE_animdata_copy_id_action(&tex->id, false);
man->mtex[b]->tex = tex;
}
}
@@ -2017,8 +2006,8 @@ static void do_single_tex_user(Main *bmain, Tex **from)
id_us_min(&tex->id);
}
else if (tex->id.us > 1) {
- texn = BKE_texture_copy(bmain, tex);
- BKE_animdata_copy_id_action(&texn->id);
+ texn = ID_NEW_SET(tex, BKE_texture_copy(bmain, tex));
+ BKE_animdata_copy_id_action(&texn->id, false);
tex->id.newid = (ID *)texn;
id_us_min(&tex->id);
*from = texn;
@@ -2095,7 +2084,7 @@ static void single_mat_users_expand(Main *bmain)
if (ma->id.tag & LIB_TAG_NEW)
for (a = 0; a < MAX_MTEX; a++)
if (ma->mtex[a])
- ID_NEW(ma->mtex[a]->object);
+ ID_NEW_REMAP(ma->mtex[a]->object);
}
/* used for copying scenes */
@@ -2245,7 +2234,6 @@ static int make_local_exec(bContext *C, wmOperator *op)
}
tag_localizable_objects(C, mode);
- BKE_main_id_clear_newpoins(bmain);
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
@@ -2262,7 +2250,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
{
if (ob->id.lib == NULL) {
- ID_NEW(ob->parent);
+ ID_NEW_REMAP(ob->parent);
}
}
CTX_DATA_END;
@@ -2330,6 +2318,7 @@ static int make_local_exec(bContext *C, wmOperator *op)
CTX_DATA_END;
}
+ BKE_main_id_clear_newpoins(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
@@ -2376,8 +2365,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
const bool copy_groups = false;
bool update_deps = false;
- BKE_main_id_clear_newpoins(bmain);
-
if (RNA_boolean_get(op->ptr, "object")) {
single_object_users(bmain, scene, v3d, flag, copy_groups);
@@ -2401,11 +2388,6 @@ static int make_single_user_exec(bContext *C, wmOperator *op)
single_object_action_users(scene, flag);
}
- /* TODO(sergey): This should not be needed, however some tool still could rely
- * on the fact, that id->newid is kept NULL by default.
- * Need to make sure all the guys are learing newid before they're
- * using it, not after.
- */
BKE_main_id_clear_newpoins(bmain);
WM_event_add_notifier(C, NC_WINDOW, NULL);
diff --git a/source/blender/editors/object/object_warp.c b/source/blender/editors/object/object_warp.c
index 9f4da87903d..92b82e2a31b 100644
--- a/source/blender/editors/object/object_warp.c
+++ b/source/blender/editors/object/object_warp.c
@@ -53,8 +53,7 @@ static void object_warp_calc_view_matrix(float r_mat_view[4][4], float r_center_
float viewmat_roll[4][4];
/* apply the rotation offset by rolling the view */
- unit_m4(mat_offset);
- rotate_m4(mat_offset, 'Z', offset_angle);
+ axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
/* apply the view and the object matrix */
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 53434b18d06..ef2f2d36ab7 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -821,10 +821,9 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
flip_v3_v3(mirror, cache->true_location, symm);
if (axis != 0) {
- float mat[4][4];
- unit_m4(mat);
- rotate_m4(mat, axis, angle);
- mul_m4_v3(mat, mirror);
+ float mat[3][3];
+ axis_angle_to_mat3_single(mat, axis, angle);
+ mul_m3_v3(mat, mirror);
}
/* distsq = len_squared_v3v3(mirror, cache->traced_location); */
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 2c678457025..d6300b74aea 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -442,6 +442,9 @@ static void id_local_cb(
if (id_make_local(bmain, tselem->id, false, false) == false) {
id_clear_lib_data(bmain, tselem->id);
}
+ else {
+ BKE_main_id_clear_newpoins(bmain);
+ }
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 3b499a81831..d1c75b01157 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1099,8 +1099,12 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
tselem->flag &= ~TSE_CLOSED;
if (TSELEM_OPEN(tselem, soops)) {
- for (a = 0; a < tot; a++)
- outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
+ for (a = 0; a < tot; a++) {
+ RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr);
+ if (!(RNA_property_flag(propptr.data) & PROP_HIDDEN)) {
+ outliner_add_element(soops, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a);
+ }
+ }
}
else if (tot)
te->flag |= TE_LAZY_CLOSED;
@@ -1632,11 +1636,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
outliner_free_tree(&soops->tree);
outliner_storage_cleanup(soops);
- /* clear ob id.new flags */
- for (Object *ob = mainvar->object.first; ob; ob = ob->id.next) {
- ob->id.newid = NULL;
- }
-
/* options */
if (soops->outlinevis == SO_LIBRARIES) {
Library *lib;
@@ -1822,6 +1821,8 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
outliner_sort(&soops->tree);
}
outliner_filter_tree(soops, &soops->tree);
+
+ BKE_main_id_clear_newpoins(mainvar);
}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index b37a6740891..7ac176f82b1 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -2719,6 +2719,11 @@ bool draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base,
else {
/* Draw Pose */
if (ob->pose && ob->pose->chanbase.first) {
+ /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
+ if (ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(ob, arm);
+ }
+
/* drawing posemode selection indices or colors only in these cases */
if (!(base->flag & OB_FROMDUPLI)) {
if (G.f & G_PICKSEL) {
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 9184e4723a8..201209789a2 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -125,7 +125,7 @@ static bool use_depth(const bContext *C)
void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4])
{
RegionView3D *rv3d = ar->regiondata;
- rctf cameraborder;
+
/* setup window matrices */
if (winmat)
@@ -139,7 +139,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
else
view3d_viewmatrix_set(scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
- /* update utilitity matrices */
+ /* update utility matrices */
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
invert_m4_m4(rv3d->viewinv, rv3d->viewmat);
@@ -148,6 +148,7 @@ void ED_view3d_update_viewmat(Scene *scene, View3D *v3d, ARegion *ar, float view
/* store window coordinates scaling/offset */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ rctf cameraborder;
ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
@@ -1447,6 +1448,16 @@ static void view3d_draw_grid(const bContext *C, ARegion *ar)
* Also for now always assume depth is there, so we
* draw on top of it.
*/
+ /**
+ * Calculate pixel-size factor once, is used for lamps and object centers.
+ * Used by #ED_view3d_pixel_size and typically not accessed directly.
+ *
+ * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
+ * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
+ * but in perspective mode its offset by the near-clip.
+ *
+ * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
+ */
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 59442e89787..50aec737c8e 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -459,7 +459,7 @@ static void stitch_calculate_island_snapping(
island_stitch_data[i].num_rot_elements_neg) / totelem;
}
- rotate_m2(rotation_mat, rotation);
+ angle_to_mat2(rotation_mat, rotation);
numOfIslandUVs = getNumOfIslandUvs(state->element_map, i);
element = &state->element_map->buf[state->element_map->islandIndices[i]];
for (j = 0; j < numOfIslandUVs; j++, element++) {
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 52aab419e03..e8fd4b8b8b1 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -184,7 +184,10 @@ void gpu_extensions_init(void)
GG.device = GPU_DEVICE_INTEL;
GG.driver = GPU_DRIVER_OFFICIAL;
}
- else if (strstr(renderer, "Mesa DRI R") || (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI "))) {
+ else if ((strstr(renderer, "Mesa DRI R")) ||
+ (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
+ (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD ")))
+ {
GG.device = GPU_DEVICE_ATI;
GG.driver = GPU_DRIVER_OPENSOURCE;
}
diff --git a/source/blender/imbuf/intern/oiio/CMakeLists.txt b/source/blender/imbuf/intern/oiio/CMakeLists.txt
index c873fa3f32d..a4fb9c5aee1 100644
--- a/source/blender/imbuf/intern/oiio/CMakeLists.txt
+++ b/source/blender/imbuf/intern/oiio/CMakeLists.txt
@@ -49,6 +49,11 @@ if(WITH_OPENIMAGEIO)
${OPENIMAGEIO_INCLUDE_DIRS}
${BOOST_INCLUDE_DIR}
)
+ if(WITH_IMAGE_OPENEXR)
+ list(APPEND INC_SYS
+ ${OPENEXR_INCLUDE_DIRS}
+ )
+ endif()
add_definitions(-DWITH_OPENIMAGEIO)
endif()
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 7bbbb8addcc..91b8c605996 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -289,9 +289,9 @@ typedef enum ID_Type {
#endif
#define GS(a) (CHECK_TYPE_ANY(a, char *, const char *, char [66], const char[66]), (*((const short *)(a))))
-#define ID_NEW(a) if ( (a) && (a)->id.newid ) (a) = (void *)(a)->id.newid
-#define ID_NEW_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; }
-#define ID_NEW_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; }
+#define ID_NEW_SET(_id, _idn) \
+ (((ID *)(_id))->newid = (ID *)(_idn), ((ID *)(_id))->newid->tag |= LIB_TAG_NEW, (void *)((ID *)(_id))->newid)
+#define ID_NEW_REMAP(a) if ((a) && (a)->id.newid) (a) = (void *)(a)->id.newid
/* id->flag (persitent). */
enum {
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 46b30f41f5b..3a7e2b6f7f8 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -811,7 +811,10 @@ typedef struct NodeShaderTexPointDensity {
short color_source;
short ob_color_source;
char vertex_attribute_name[64]; /* vertex attribute layer for color source, MAX_CUSTOMDATA_LAYER_NAME */
+ /* Used at runtime only by sampling RNA API. */
PointDensity pd;
+ int cached_resolution;
+ int pad2;
} NodeShaderTexPointDensity;
/* TEX_output */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 30d81df07ef..1c4db5289ef 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -866,14 +866,6 @@ typedef enum eNdof_Flag {
#define NDOF_PIXELS_PER_SECOND 600.0f
-/* compute_device_type */
-typedef enum eCompute_Device_Type {
- USER_COMPUTE_DEVICE_NONE = 0,
- USER_COMPUTE_DEVICE_OPENCL = 1,
- USER_COMPUTE_DEVICE_CUDA = 2,
-} eCompute_Device_Type;
-
-
typedef enum eMultiSample_Type {
USER_MULTISAMPLE_NONE = 0,
USER_MULTISAMPLE_2 = 2,
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index b2b97ce85d9..5f54852328c 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -1536,7 +1536,11 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
const char *nextfunc = (const char *)cprop->next;
const char *item_type = (const char *)cprop->item_type;
- if (dp->dnatype && STREQ(dp->dnatype, "ListBase")) {
+ if (cprop->length) {
+ /* always generate if we have a manual implementation */
+ cprop->length = (void *)rna_def_property_length_func(f, srna, prop, dp, (const char *)cprop->length);
+ }
+ else if (dp->dnatype && STREQ(dp->dnatype, "ListBase")) {
/* pass */
}
else if (dp->dnalengthname || dp->dnalengthfixed) {
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index ee662bc2b0d..aef88af118a 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -346,7 +346,9 @@ static struct ID *rna_ID_make_local(struct ID *self, Main *bmain, int clear_prox
id_make_local(bmain, self, false, false);
}
- return self->newid ? self->newid : self;
+ ID *ret_id = self->newid ? self->newid : self;
+ BKE_id_clear_newpoin(self);
+ return ret_id;
}
@@ -1006,9 +1008,9 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Make this datablock local, return local one "
"(may be a copy of the original, in case it is also indirectly used)");
RNA_def_function_flag(func, FUNC_USE_MAIN);
- RNA_def_boolean(func, "clear_proxy", true, "",
- "Whether to clear proxies (the default behavior); can cause proxies to be duplicated"
- " when still referred to from another library");
+ parm = RNA_def_boolean(func, "clear_proxy", true, "",
+ "Whether to clear proxies (the default behavior, "
+ "note that if object has to be duplicated to be made local, proxies are always cleared)");
RNA_def_property_flag(parm, PROP_PYFUNC_OPTIONAL);
parm = RNA_def_pointer(func, "id", "ID", "", "This ID, or the new ID if it was copied");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 7ba89538b18..16aa60e1b91 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -585,11 +585,11 @@ static bGPDframe *rna_GPencil_frame_copy(bGPDlayer *layer, bGPDframe *src)
static bGPDlayer *rna_GPencil_layer_new(bGPdata *gpd, const char *name, int setactive)
{
- bGPDlayer *gl = BKE_gpencil_layer_addnew(gpd, name, setactive != 0);
+ bGPDlayer *gpl = BKE_gpencil_layer_addnew(gpd, name, setactive != 0);
WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
- return gl;
+ return gpl;
}
static void rna_GPencil_layer_remove(bGPdata *gpd, ReportList *reports, PointerRNA *layer_ptr)
@@ -1354,7 +1354,7 @@ static void rna_def_gpencil_layers_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new grease pencil layer");
parm = RNA_def_string(func, "name", "GPencilLayer", MAX_NAME, "Name", "Name of the layer");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "set_active", 0, "Set Active", "Set the newly created layer to the active layer");
+ RNA_def_boolean(func, "set_active", true, "Set Active", "Set the newly created layer to the active layer");
parm = RNA_def_pointer(func, "layer", "GPencilLayer", "", "The newly created layer");
RNA_def_function_return(func, parm);
@@ -1443,7 +1443,7 @@ static void rna_def_gpencil_palettecolor(BlenderRNA *brna)
prop = RNA_def_property(srna, "ghost", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PC_COLOR_ONIONSKIN);
RNA_def_property_ui_icon(prop, ICON_GHOST_ENABLED, 0);
- RNA_def_property_ui_text(prop, "Ghost", "Display the color in onion skinning");
+ RNA_def_property_ui_text(prop, "Show in Ghosts", "Display strokes using this color when showing onion skins");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
/* Draw Style */
@@ -1557,7 +1557,7 @@ static void rna_def_gpencil_palettes_api(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Add a new grease pencil palette");
parm = RNA_def_string(func, "name", "GPencilPalette", MAX_NAME, "Name", "Name of the palette");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_boolean(func, "set_active", 0, "Set Active", "Activate the newly created palette");
+ RNA_def_boolean(func, "set_active", true, "Set Active", "Activate the newly created palette");
parm = RNA_def_pointer(func, "palette", "GPencilPalette", "", "The newly created palette");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c
index 59f079b4259..d5d6f609a03 100644
--- a/source/blender/makesrna/intern/rna_main.c
+++ b/source/blender/makesrna/intern/rna_main.c
@@ -392,7 +392,7 @@ void RNA_def_main(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Autopack", "Automatically pack all external data into .blend file");
prop = RNA_def_int_vector(srna, "version", 3, NULL, 0, INT_MAX,
- "Version", "Version of the blender the .blend was saved with", 0, INT_MAX);
+ "Version", "Version of Blender the .blend was saved with", 0, INT_MAX);
RNA_def_property_int_funcs(prop, "rna_Main_version_get", NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_flag(prop, PROP_THICK_WRAP);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index e68f75a1399..772c1d9e4ed 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3076,6 +3076,9 @@ void rna_ShaderNodePointDensity_density_cache(bNode *self,
sizeof(pd->vertex_attribute_name));
}
+ /* Store resolution, so it can be changed in the UI. */
+ shader_point_density->cached_resolution = shader_point_density->resolution;
+
/* Single-threaded sampling of the voxel domain. */
RE_point_density_cache(scene,
pd,
@@ -3090,15 +3093,15 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
{
NodeShaderTexPointDensity *shader_point_density = self->storage;
PointDensity *pd = &shader_point_density->pd;
+ const int resolution = shader_point_density->cached_resolution;
if (scene == NULL) {
*length = 0;
return;
}
- *length = 4 * shader_point_density->resolution *
- shader_point_density->resolution *
- shader_point_density->resolution;
+ /* TODO(sergey): Will likely overflow, but how to pass size_t via RNA? */
+ *length = 4 * resolution * resolution * resolution;
if (*values == NULL) {
*values = MEM_mallocN(sizeof(float) * (*length), "point density dynamic array");
@@ -3106,13 +3109,14 @@ void rna_ShaderNodePointDensity_density_calc(bNode *self,
/* Single-threaded sampling of the voxel domain. */
RE_point_density_sample(scene, pd,
- shader_point_density->resolution,
+ resolution,
settings == 1,
*values);
/* We're done, time to clean up. */
BKE_texture_pointdensity_free_data(pd);
memset(pd, 0, sizeof(*pd));
+ shader_point_density->cached_resolution = 0.0f;
}
void rna_ShaderNodePointDensity_density_minmax(bNode *self,
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index b3aea604926..6140fcc18cd 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -124,6 +124,14 @@ static EnumPropertyItem rna_enum_language_default_items[] = {
#endif
+static void rna_userdef_version_get(PointerRNA *ptr, int *value)
+{
+ UserDef *userdef = (UserDef *)ptr->data;
+ value[0] = userdef->versionfile / 100;
+ value[1] = userdef->versionfile % 100;
+ value[2] = userdef->subversionfile;
+}
+
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_WINDOW, NULL);
@@ -4190,6 +4198,14 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "OpenSubdiv Compute Type", "Type of computer back-end used with OpenSubdiv");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_userdef_opensubdiv_update");
#endif
+
+#ifdef WITH_CYCLES
+ prop = RNA_def_property(srna, "legacy_compute_device_type", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "compute_device_type");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ RNA_def_property_ui_text(prop, "Legacy Compute Device Type", "For backwards compatibility only");
+#endif
}
static void rna_def_userdef_input(BlenderRNA *brna)
@@ -4707,6 +4723,12 @@ void RNA_def_userdef(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_UserDef_system_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "System & OpenGL", "Graphics driver and operating system settings");
+ prop = RNA_def_int_vector(srna, "version", 3, NULL, 0, INT_MAX,
+ "Version", "Version of Blender the userpref.blend was saved with", 0, INT_MAX);
+ RNA_def_property_int_funcs(prop, "rna_userdef_version_get", NULL, NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_THICK_WRAP);
+
rna_def_userdef_view(brna);
rna_def_userdef_edit(brna);
rna_def_userdef_input(brna);
diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c
index df94975e274..290e19736bb 100644
--- a/source/blender/modifiers/intern/MOD_screw.c
+++ b/source/blender/modifiers/intern/MOD_screw.c
@@ -798,13 +798,11 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (ltmd->ob_axis) {
axis_angle_normalized_to_mat3(mat3, axis_vec, step_angle);
- copy_m4_m3(mat, mat3);
}
else {
- unit_m4(mat);
- rotate_m4(mat, axis_char, step_angle);
- copy_m3_m4(mat3, mat);
+ axis_angle_to_mat3_single(mat3, axis_char, step_angle);
}
+ copy_m4_m3(mat, mat3);
if (screw_ofs)
madd_v3_v3fl(mat[3], axis_vec, screw_ofs * ((float)step / (float)(step_tot - 1)));
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c
index ff1761eb6d7..1eb8644a9a6 100644
--- a/source/blender/python/mathutils/mathutils_bvhtree.c
+++ b/source/blender/python/mathutils/mathutils_bvhtree.c
@@ -817,13 +817,14 @@ static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, P
PyErr_Format(PyExc_ValueError,
"%s: index %d must be less than %d",
error_prefix, plink->poly[j], coords_len);
-
- Py_DECREF(py_tricoords_fast);
+ /* decref below */
valid = false;
break;
}
}
+ Py_DECREF(py_tricoords_fast);
+
if (py_tricoords_len >= 3) {
tris_len += (py_tricoords_len - 2);
}
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt
index aa0a213cf64..04a79f6498f 100644
--- a/source/creator/CMakeLists.txt
+++ b/source/creator/CMakeLists.txt
@@ -1185,7 +1185,7 @@ if(WIN32 AND NOT WITH_PYTHON_MODULE)
message(FATAL_ERROR "Windows 10 SDK directory not found")
endif()
endif()
-
+ FILE(TO_CMAKE_PATH ${KITSPATH} KITSPATH)
install(
FILES
${KITSPATH}/api-ms-win-core-file-l1-2-0.dll