diff options
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 |