Merge branch 'master' into blender2.8
authorBastien Montagne <montagne29@wanadoo.fr>
Tue, 7 Jun 2016 07:58:27 +0000 (09:58 +0200)
committerBastien Montagne <montagne29@wanadoo.fr>
Tue, 7 Jun 2016 07:59:26 +0000 (09:59 +0200)
Conflicts:
source/blender/blenkernel/intern/particle.c
source/blender/editors/transform/transform_snap_object.c

104 files changed:
build_files/buildbot/slave_compile.py
doc/python_api/sphinx_doc_gen.sh
extern/wcwidth/README.blender [new file with mode: 0644]
intern/cycles/blender/addon/ui.py
intern/cycles/bvh/bvh_build.cpp
intern/cycles/device/device_cuda.cpp
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/geom/geom_triangle_intersect.h
intern/cycles/kernel/kernel_light.h
intern/cycles/kernel/kernel_volume.h
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/render/object.h
intern/cycles/util/CMakeLists.txt
intern/cycles/util/util_math.h
intern/cycles/util/util_system.cpp
intern/cycles/util/util_system.h
intern/cycles/util/util_task.cpp
intern/cycles/util/util_thread.cpp [new file with mode: 0644]
intern/cycles/util/util_thread.h
intern/cycles/util/util_windows.cpp [new file with mode: 0644]
intern/cycles/util/util_windows.h
release/scripts/modules/bl_i18n_utils/utils_spell_check.py
release/scripts/presets/interface_theme/blender_24x.xml
release/scripts/startup/bl_operators/wm.py
release/scripts/startup/bl_ui/__init__.py
release/scripts/startup/bl_ui/properties_data_modifier.py
source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/BKE_fcurve.h
source/blender/blenkernel/BKE_object.h
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/autoexec.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/editderivedmesh.c
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/fcurve.c
source/blender/blenkernel/intern/idcode.c
source/blender/blenkernel/intern/object_update.c
source/blender/blenkernel/intern/pbvh.c
source/blender/blenkernel/intern/pbvh_intern.h
source/blender/blenlib/intern/BLI_ghash.c
source/blender/blenlib/intern/BLI_mempool.c
source/blender/blenlib/intern/array_store.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/versioning_270.c
source/blender/bmesh/tools/bmesh_bevel.c
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/DocumentImporter.cpp
source/blender/collada/ImportSettings.h
source/blender/collada/MeshImporter.cpp
source/blender/collada/MeshImporter.h
source/blender/collada/SkinInfo.cpp
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/collada/collada_utils.h
source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/eval/deg_eval_flush.cc
source/blender/editors/animation/drivers.c
source/blender/editors/armature/editarmature_sketch.c
source/blender/editors/curve/editcurve.c
source/blender/editors/include/ED_physics.h
source/blender/editors/include/ED_screen_types.h
source/blender/editors/include/ED_transform.h
source/blender/editors/include/ED_transform_snap_object_context.h
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_ops.c
source/blender/editors/io/io_collada.c
source/blender/editors/mesh/editmesh_bevel.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/object/object_add.c
source/blender/editors/physics/rigidbody_constraint.c
source/blender/editors/physics/rigidbody_object.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_cursor.c
source/blender/editors/space_action/action_edit.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_ruler.c
source/blender/editors/space_view3d/view3d_walk.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/transform/transform_snap_object.c
source/blender/gpu/GPU_buffers.h
source/blender/gpu/intern/gpu_buffers.c
source/blender/gpu/intern/gpu_init_exit.c
source/blender/makesdna/DNA_ID.h
source/blender/makesdna/DNA_anim_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene_api.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/modifiers/intern/MOD_normal_edit.c
source/blender/modifiers/intern/MOD_shapekey.c
source/blender/render/intern/include/rayintersection.h
source/blender/render/intern/raytrace/rayobject.cpp
source/blender/render/intern/source/render_result.c
source/blender/windowmanager/intern/wm_files.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt
source/creator/creator_args.c

index 9a874e9..4fb879a 100644 (file)
@@ -77,10 +77,10 @@ if 'cmake' in builder:
     elif builder.startswith('win'):
       if builder.endswith('_vc2015'):
         if builder.startswith('win64'):
-            cmake_options.extend(['-G', 'Visual Studio 14 2015 Win64'])
+            cmake_options.extend(['-G', 'Visual Studio 14 2015 Win64', b'-DCUDA_NVCC_FLAGS="-ccbin C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\"'])
         elif builder.startswith('win32'):
             bits = 32
-            cmake_options.extend(['-G', 'Visual Studio 14 2015'])
+            cmake_options.extend(['-G', 'Visual Studio 14 2015', b'-DCUDA_NVCC_FLAGS="-ccbin C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\"'])
       else:
         if builder.startswith('win64'):
             cmake_options.extend(['-G', 'Visual Studio 12 2013 Win64'])
index 7095808..1ab6bd5 100755 (executable)
@@ -61,7 +61,7 @@ if $DO_EXE_BLENDER ; then
                --python-exit-code 1 \
                --python $SPHINXBASE/sphinx_doc_gen.py
 
-       if (($? == 1)) ; then
+       if (($? != 0)) ; then
                echo "Generating documentation failed, aborting"
                exit 1
        fi
diff --git a/extern/wcwidth/README.blender b/extern/wcwidth/README.blender
new file mode 100644 (file)
index 0000000..27c8574
--- /dev/null
@@ -0,0 +1,5 @@
+Project: WC Width
+URL: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+License: ICS
+Upstream version: 2007-05-26
+Local modifications: None
index add0035..94ed3dd 100644 (file)
@@ -76,9 +76,8 @@ def use_cuda(context):
 
 def use_branched_path(context):
     cscene = context.scene.cycles
-    device_type = context.user_preferences.system.compute_device_type
 
-    return (cscene.progressive == 'BRANCHED_PATH' and device_type != 'OPENCL')
+    return (cscene.progressive == 'BRANCHED_PATH' and not use_opencl(context))
 
 
 def use_sample_all_lights(context):
@@ -704,7 +703,7 @@ class Cycles_PT_mesh_displacement(CyclesButtonsPanel, Panel):
 
         col = split.column()
         sub = col.column(align=True)
-        sub.label(text="Displacment:")
+        sub.label(text="Displacement:")
         sub.prop(cdata, "displacement_method", text="")
 
         col = split.column()
index 87a8899..d00de00 100644 (file)
@@ -205,6 +205,9 @@ void BVHBuild::add_references(BVHRange& root)
 
        foreach(Object *ob, objects) {
                if(params.top_level) {
+                       if(!ob->is_traceable()) {
+                               continue;
+                       }
                        if(!ob->mesh->is_instanced()) {
                                num_alloc_references += ob->mesh->num_triangles();
                                num_alloc_references += count_curve_segments(ob->mesh);
@@ -226,6 +229,9 @@ void BVHBuild::add_references(BVHRange& root)
 
        foreach(Object *ob, objects) {
                if(params.top_level) {
+                       if(!ob->is_traceable()) {
+                               continue;
+                       }
                        if(!ob->mesh->is_instanced())
                                add_reference_mesh(bounds, center, ob->mesh, i);
                        else
index d7ed7b4..2d40491 100644 (file)
@@ -1368,6 +1368,7 @@ void device_cuda_info(vector<DeviceInfo>& devices)
 
                /* 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) {
+                       info.description += " (Display)";
                        info.display_device = true;
                        display_devices.push_back(info);
                }
index 7c2fc1e..61c484d 100644 (file)
@@ -234,6 +234,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
                        OUTPUT ${cuda_cubin}
                        COMMAND ${CUDA_NVCC_EXECUTABLE}
                                        -arch=${arch}
+                                       ${CUDA_NVCC_FLAGS}
                                        -m${CUDA_BITS}
                                        --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda/kernel.cu
                                        -o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
index d2957ad..4e2f46d 100644 (file)
@@ -160,15 +160,10 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
 #endif
        {
 #ifdef __KERNEL_GPU__
-               float4 a = tri_b - tri_a, b = tri_c - tri_a;
-               if(len_squared(make_float3(a.y*b.z - a.z*b.y,
-                                          a.z*b.x - a.x*b.z,
-                                          a.x*b.y - a.y*b.x)) == 0.0f)
-               {
+               if(A == B && B == C) {
                        return false;
                }
 #endif
-
                /* Normalize U, V, W, and T. */
                const float inv_det = 1.0f / det;
                isect->prim = triAddr;
index 675eacf..736a884 100644 (file)
@@ -291,24 +291,13 @@ ccl_device float background_portal_pdf(KernelGlobals *kg,
                }
                num_possible++;
 
-               float t = -(dot(P, dir) - dot(lightpos, dir)) / dot(direction, dir);
-               if(t <= 1e-4f) {
-                       /* Either behind the portal or too close. */
-                       continue;
-               }
-
                float4 data1 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 1);
                float4 data2 = kernel_tex_fetch(__light_data, (p + kernel_data.integrator.portal_offset)*LIGHT_SIZE + 2);
 
                float3 axisu = make_float3(data1.y, data1.z, data1.w);
                float3 axisv = make_float3(data2.y, data2.z, data2.w);
 
-               float3 hit = P + t*direction;
-               float3 inplane = hit - lightpos;
-               /* Skip if the the ray doesn't pass through portal. */
-               if(fabsf(dot(inplane, axisu) / dot(axisu, axisu)) > 0.5f)
-                       continue;
-               if(fabsf(dot(inplane, axisv) / dot(axisv, axisv)) > 0.5f)
+               if(!ray_quad_intersect(P, direction, 1e-4f, FLT_MAX, lightpos, axisu, axisv, dir, NULL, NULL))
                        continue;
 
                portal_pdf += area_light_sample(P, &lightpos, axisu, axisv, 0.0f, 0.0f, false);
@@ -729,8 +718,8 @@ ccl_device bool lamp_light_eval(KernelGlobals *kg, int lamp, float3 P, float3 D,
 
                float3 light_P = make_float3(data0.y, data0.z, data0.w);
 
-               if(!ray_quad_intersect(P, D, t,
-                                      light_P, axisu, axisv, &ls->P, &ls->t))
+               if(!ray_quad_intersect(P, D, 0.0f, t,
+                                      light_P, axisu, axisv, Ng, &ls->P, &ls->t))
                {
                        return false;
                }
index e1ea60f..0e313b8 100644 (file)
@@ -1216,6 +1216,7 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
 #  else
        Intersection isect;
        int step = 0;
+       float3 Pend = ray->P + ray->D*ray->t;
        while(step < 2 * VOLUME_STACK_SIZE &&
              scene_intersect_volume(kg,
                                     &volume_ray,
@@ -1227,7 +1228,9 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
 
                /* Move ray forward. */
                volume_ray.P = ray_offset(stack_sd->P, -stack_sd->Ng);
-               volume_ray.t -= stack_sd->ray_length;
+               if(volume_ray.t != FLT_MAX) {
+                       volume_ray.D = normalize_len(Pend - volume_ray.P, &volume_ray.t);
+               }
                ++step;
        }
 #  endif
index 4656b3d..df0fee6 100644 (file)
@@ -3383,7 +3383,7 @@ void MixNode::compile(OSLCompiler& compiler)
 
 bool MixNode::constant_fold(ShaderGraph *graph, ShaderOutput *, ShaderInput *optimized)
 {
-       if(type != ustring("Mix")) {
+       if(type != NODE_MIX_BLEND) {
                return false;
        }
 
index 9ee1a9e..644e581 100644 (file)
@@ -225,6 +225,16 @@ vector<float> Object::motion_times()
        return times;
 }
 
+bool Object::is_traceable()
+{
+       /* Mesh itself can be empty,can skip all such objects. */
+       if (bounds.size() == make_float3(0.0f, 0.0f, 0.0f)) {
+               return false;
+       }
+       /* TODO(sergey): Check for mesh vertices/curves. visibility flags. */
+       return true;
+}
+
 /* Object Manager */
 
 ObjectManager::ObjectManager()
index 57614c9..7ab73f3 100644 (file)
@@ -68,6 +68,11 @@ public:
        void apply_transform(bool apply_to_motion);
 
        vector<float> motion_times();
+
+       /* Check whether object is traceable and it worth adding it to
+        * kernel scene.
+        */
+       bool is_traceable();
 };
 
 /* Object Manager */
index cceec8d..e6140b3 100644 (file)
@@ -19,8 +19,10 @@ set(SRC
        util_simd.cpp
        util_system.cpp
        util_task.cpp
+       util_thread.cpp
        util_time.cpp
        util_transform.cpp
+       util_windows.cpp
 )
 
 if(NOT CYCLES_STANDALONE_REPOSITORY)
index 32924f9..53944ec 100644 (file)
@@ -1479,21 +1479,25 @@ ccl_device bool ray_triangle_intersect_uv(
        return true;
 }
 
-ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_t,
-                                   float3 quad_P, float3 quad_u, float3 quad_v,
+ccl_device bool ray_quad_intersect(float3 ray_P, float3 ray_D, float ray_mint, float ray_maxt,
+                                   float3 quad_P, float3 quad_u, float3 quad_v, float3 quad_n,
                                    float3 *isect_P, float *isect_t)
 {
-       float3 v0 = quad_P - quad_u*0.5f - quad_v*0.5f;
-       float3 v1 = quad_P + quad_u*0.5f - quad_v*0.5f;
-       float3 v2 = quad_P + quad_u*0.5f + quad_v*0.5f;
-       float3 v3 = quad_P - quad_u*0.5f + quad_v*0.5f;
+       float t = -(dot(ray_P, quad_n) - dot(quad_P, quad_n)) / dot(ray_D, quad_n);
+       if(t < ray_mint || t > ray_maxt)
+               return false;
 
-       if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v1, v2, isect_P, isect_t))
-               return true;
-       else if(ray_triangle_intersect(ray_P, ray_D, ray_t, v0, v2, v3, isect_P, isect_t))
-               return true;
-       
-       return false;
+       float3 hit = ray_P + t*ray_D;
+       float3 inplane = hit - quad_P;
+       if(fabsf(dot(inplane, quad_u) / dot(quad_u, quad_u)) > 0.5f)
+               return false;
+       if(fabsf(dot(inplane, quad_v) / dot(quad_v, quad_v)) > 0.5f)
+               return false;
+
+       if(isect_P) *isect_P = hit;
+       if(isect_t) *isect_t = t;
+
+       return true;
 }
 
 /* projections */
index 4ff0ee9..d5fac9a 100644 (file)
@@ -15,7 +15,9 @@
  */
 
 #include "util_system.h"
+
 #include "util_debug.h"
+#include "util_logging.h"
 #include "util_types.h"
 #include "util_string.h"
 
 
 CCL_NAMESPACE_BEGIN
 
-int system_cpu_thread_count()
+int system_cpu_group_count()
 {
-       static uint count = 0;
-
-       if(count > 0)
-               return count;
+#ifdef _WIN32
+       util_windows_init_numa_groups();
+       return GetActiveProcessorGroupCount();
+#else
+       /* TODO(sergey): Need to adopt for other platforms. */
+       return 1;
+#endif
+}
 
+int system_cpu_group_thread_count(int group)
+{
+       /* TODO(sergey): Need make other platforms aware of groups. */
 #ifdef _WIN32
-       SYSTEM_INFO info;
-       GetSystemInfo(&info);
-       count = (uint)info.dwNumberOfProcessors;
+       util_windows_init_numa_groups();
+       return GetActiveProcessorCount(group);
 #elif defined(__APPLE__)
+       (void)group;
+       int count;
        size_t len = sizeof(count);
        int mib[2] = { CTL_HW, HW_NCPU };
-       
        sysctl(mib, 2, &count, &len, NULL, 0);
+       return count;
 #else
-       count = (uint)sysconf(_SC_NPROCESSORS_ONLN);
+       (void)group;
+       return sysconf(_SC_NPROCESSORS_ONLN);
 #endif
+}
+
+int system_cpu_thread_count()
+{
+       static uint count = 0;
 
-       if(count < 1)
+       if(count > 0) {
+               return count;
+       }
+
+       int max_group = system_cpu_group_count();
+       VLOG(1) << "Detected " << max_group << " CPU groups.";
+       for(int group = 0; group < max_group; ++group) {
+               int num_threads = system_cpu_group_thread_count(group);
+               VLOG(1) << "Group " << group
+                       << " has " << num_threads << " threads.";
+               count += num_threads;
+       }
+
+       if(count < 1) {
                count = 1;
+       }
 
        return count;
 }
index 4e7e00f..557aab6 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
+/* Get number of available CPU groups. */
+int system_cpu_group_count();
+
+/* Get number of threads/processors in the specified group. */
+int system_cpu_group_thread_count(int group);
+
+/* Get total number of threads in all groups. */
 int system_cpu_thread_count();
+
 string system_cpu_brand_string();
 int system_cpu_bits();
 bool system_cpu_support_sse2();
index d86aa8a..352ba81 100644 (file)
@@ -16,6 +16,7 @@
 
 #include "util_debug.h"
 #include "util_foreach.h"
+#include "util_logging.h"
 #include "util_system.h"
 #include "util_task.h"
 #include "util_time.h"
@@ -198,12 +199,30 @@ void TaskScheduler::init(int num_threads)
                        /* automatic number of threads */
                        num_threads = system_cpu_thread_count();
                }
+               VLOG(1) << "Creating pool of " << num_threads << " threads.";
 
                /* launch threads that will be waiting for work */
                threads.resize(num_threads);
 
-               for(size_t i = 0; i < threads.size(); i++)
-                       threads[i] = new thread(function_bind(&TaskScheduler::thread_run, i + 1));
+               int num_groups = system_cpu_group_count();
+               int thread_index = 0;
+               for(int group = 0; group < num_groups; ++group) {
+                       /* NOTE: That's not really efficient from threading point of view,
+                        * but it is simple to read and it doesn't make sense to use more
+                        * user-specified threads than logical threads anyway.
+                        */
+                       int num_group_threads = (group == num_groups - 1)
+                               ? (threads.size() - thread_index)
+                               : system_cpu_group_thread_count(group);
+                       for(int group_thread = 0;
+                               group_thread < num_group_threads && thread_index < threads.size();
+                               ++group_thread, ++thread_index)
+                       {
+                               threads[thread_index] = new thread(function_bind(&TaskScheduler::thread_run,
+                                                                                thread_index + 1),
+                                                                  group);
+                       }
+               }
        }
        
        users++;
diff --git a/intern/cycles/util/util_thread.cpp b/intern/cycles/util/util_thread.cpp
new file mode 100644 (file)
index 0000000..3db8b4b
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#include "util_thread.h"
+
+#include "util_system.h"
+#include "util_windows.h"
+
+CCL_NAMESPACE_BEGIN
+
+thread::thread(function<void(void)> run_cb, int group)
+  : run_cb_(run_cb),
+    joined_(false),
+       group_(group)
+{
+       pthread_create(&pthread_id_, NULL, run, (void*)this);
+}
+
+thread::~thread()
+{
+       if(!joined_) {
+               join();
+       }
+}
+
+void *thread::run(void *arg)
+{
+       thread *self = (thread*)(arg);
+       if(self->group_ != -1) {
+#ifdef _WIN32
+               HANDLE thread_handle = GetCurrentThread();
+               GROUP_AFFINITY group_affinity = { 0 };
+               int num_threads = system_cpu_group_thread_count(self->group_);
+               group_affinity.Group = self->group_;
+               group_affinity.Mask = (num_threads == 64)
+                                             ? -1
+                                             :  (1ull << num_threads) - 1;
+               if(SetThreadGroupAffinity(thread_handle, &group_affinity, NULL) == 0) {
+                       fprintf(stderr, "Error setting thread affinity.\n");
+               }
+#endif
+       }
+       self->run_cb_();
+       return NULL;
+}
+
+bool thread::join()
+{
+       joined_ = true;
+       return pthread_join(pthread_id_, NULL) == 0;
+}
+
+CCL_NAMESPACE_END
index 59575f3..427c633 100644 (file)
@@ -52,37 +52,17 @@ typedef boost::condition_variable thread_condition_variable;
 
 class thread {
 public:
-       thread(function<void(void)> run_cb_)
+       thread(function<void(void)> run_cb, int group = -1);
+       ~thread();
 
-       {
-               joined = false;
-               run_cb = run_cb_;
-
-               pthread_create(&pthread_id, NULL, run, (void*)this);
-       }
-
-       ~thread()
-       {
-               if(!joined)
-                       join();
-       }
-
-       static void *run(void *arg)
-       {
-               ((thread*)arg)->run_cb();
-               return NULL;
-       }
-
-       bool join()
-       {
-               joined = true;
-               return pthread_join(pthread_id, NULL) == 0;
-       }
+       static void *run(void *arg);
+       bool join();
 
 protected:
-       function<void(void)> run_cb;
-       pthread_t pthread_id;
-       bool joined;
+       function<void(void)> run_cb_;
+       pthread_t pthread_id_;
+       bool joined_;
+       int group_;
 };
 
 /* Own wrapper around pthread's spin lock to make it's use easier. */
diff --git a/intern/cycles/util/util_windows.cpp b/intern/cycles/util/util_windows.cpp
new file mode 100644 (file)
index 0000000..ee5b3fd
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#include "util_windows.h"
+
+#ifdef _WIN32
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef _M_X64
+#  include <VersionHelpers.h>
+#endif
+
+#if _WIN32_WINNT < 0x0601
+tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
+tGetActiveProcessorCount *GetActiveProcessorCount;
+tSetThreadGroupAffinity *SetThreadGroupAffinity;
+#endif
+
+static WORD GetActiveProcessorGroupCount_stub()
+{
+       return 1;
+}
+
+static DWORD GetActiveProcessorCount_stub(WORD /*GroupNumber*/)
+{
+       SYSTEM_INFO info;
+       GetSystemInfo(&info);
+       return info.dwNumberOfProcessors;
+}
+
+static BOOL SetThreadGroupAffinity_stub(
+        HANDLE /*hThread*/,
+        const GROUP_AFFINITY  * /*GroupAffinity*/,
+        PGROUP_AFFINITY /*PreviousGroupAffinity*/)
+{
+       return TRUE;
+}
+
+static bool supports_numa()
+{
+#ifndef _M_X64
+       return false;
+#else
+       return IsWindows7OrGreater();
+#endif
+}
+
+void util_windows_init_numa_groups()
+{
+       static bool initialized = false;
+       if(initialized) {
+               return;
+       }
+       initialized = true;
+#if _WIN32_WINNT < 0x0601
+       if(!supports_numa()) {
+               /* Use stubs on platforms which doesn't have rean NUMA/Groups. */
+               GetActiveProcessorGroupCount = GetActiveProcessorGroupCount_stub;
+               GetActiveProcessorCount = GetActiveProcessorCount_stub;
+               SetThreadGroupAffinity = SetThreadGroupAffinity_stub;
+               return;
+       }
+       HMODULE kernel = GetModuleHandleA("kernel32.dll");
+#  define READ_SYMBOL(sym) sym = (t##sym*)GetProcAddress(kernel, #sym)
+       READ_SYMBOL(GetActiveProcessorGroupCount);
+       READ_SYMBOL(GetActiveProcessorCount);
+       READ_SYMBOL(SetThreadGroupAffinity);
+#  undef READ_SUMBOL
+#endif
+}
+
+CCL_NAMESPACE_END
+
+#endif  /* _WIN32 */
index f67e34d..ac61d53 100644 (file)
 
 #include <windows.h>
 
+CCL_NAMESPACE_BEGIN
+
+#if _WIN32_WINNT < 0x0601
+typedef WORD tGetActiveProcessorGroupCount();
+typedef DWORD tGetActiveProcessorCount(WORD GroupNumber);
+typedef BOOL tSetThreadGroupAffinity(HANDLE hThread,
+                                     const GROUP_AFFINITY  *GroupAffinity,
+                                     PGROUP_AFFINITY PreviousGroupAffinity);
+
+extern tGetActiveProcessorGroupCount *GetActiveProcessorGroupCount;
+extern tGetActiveProcessorCount *GetActiveProcessorCount;
+extern tSetThreadGroupAffinity *SetThreadGroupAffinity;
+#endif
+
+/* Make sure NUMA and processor groups API is initialized. */
+void util_windows_init_numa_groups();
+
+CCL_NAMESPACE_END
+
 #endif  /* WIN32 */
 
 #endif /* __UTIL_WINDOWS_H__ */
index df014e8..636b6b0 100644 (file)
@@ -58,7 +58,7 @@ class SpellChecker:
         "vertices",
 
         # Merged words
-        "addon", "addons",
+        #~ "addon", "addons",
         "antialiasing",
         "arcsine", "arccosine", "arctangent",
         "autoclip",
@@ -118,6 +118,7 @@ class SpellChecker:
         "localview",
         "lookup", "lookups",
         "mathutils",
+        "micropolygon",
         "midlevel",
         "midground",
         "mixdown",
@@ -127,6 +128,7 @@ class SpellChecker:
         "multires", "multiresolution",
         "multisampling",
         "multitexture",
+        "multithreaded", 
         "multiuser",
         "multiview",
         "namespace",
@@ -412,6 +414,7 @@ class SpellChecker:
         # Blender terms
         "audaspace",
         "bbone",
+        "bendy",  # bones
         "bmesh",
         "breakdowner",
         "bspline",
@@ -473,9 +476,10 @@ class SpellChecker:
         "wpaint",
         "uvwarp",
 
-        # Algorithm names
+        # Algorithm/library names
         "ashikhmin",  # Ashikhmin-Shirley
         "beckmann",
+        "blosc",
         "catmull",
         "catrom",
         "chebychev",
index ae42b60..90730ae 100644 (file)
                              header="#b4b4b4"
                              header_text="#000000"
                              header_text_hi="#ffffff"
-                             button="#727272ff"
+                             button="#b4b4b457"
                              button_title="#000000"
                              button_text="#000000"
                              button_text_hi="#ffffff"
index 76d41d9..cc8921f 100644 (file)
@@ -1357,7 +1357,10 @@ class WM_OT_properties_add(Operator):
 
             return prop_new
 
-        prop = unique_name(item.keys())
+        prop = unique_name(
+                {*item.keys(),
+                 *type(item).bl_rna.properties.keys(),
+                 })
 
         item[prop] = 1.0
         rna_idprop_ui_prop_update(item, prop)
index 46dd59a..ac15039 100644 (file)
@@ -125,7 +125,7 @@ def register():
     WindowManager.addon_filter = EnumProperty(
             items=addon_filter_items,
             name="Category",
-            description="Filter addons by category",
+            description="Filter add-ons by category",
             )
 
     WindowManager.addon_support = EnumProperty(
index 4d694b0..7e60671 100644 (file)
@@ -1384,6 +1384,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         sub = row.row(align=True)
         sub.active = has_vgroup
         sub.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT')
+        subcol.prop(md, "mix_limit")
 
     def CORRECTIVE_SMOOTH(self, layout, ob, md):
         is_bind = md.is_bind
index dc75174..6524aff 100644 (file)
@@ -177,7 +177,7 @@ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene,
 
 /* TODO(sergey): This is mainly a temp public function. */
 struct FCurve;
-bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu);
+bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval);
 
 /* ------------ Specialized API --------------- */
 /* There are a few special tools which require these following functions. They are NOT to be used
index 2022d11..bb4eb65 100644 (file)
@@ -279,7 +279,7 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], float v4[2]);
 /* evaluate fcurve */
 float evaluate_fcurve(struct FCurve *fcu, float evaltime);
 /* evaluate fcurve and store value */
-void calculate_fcurve(struct FCurve *fcu, float ctime);
+float calculate_fcurve(struct FCurve *fcu, float evaltime);
 
 /* ************* F-Curve Samples API ******************** */
 
index 1bb1e5f..7f0234a 100644 (file)
@@ -205,6 +205,8 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
                                struct Scene *scene,
                                struct Object *ob);
 
+void BKE_object_eval_proxy_backlink(struct EvaluationContext *eval_ctx, struct Object *ob);
+
 void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
                                    struct Scene *scene,
                                    struct Object *ob);
index 9afee55..7e01b88 100644 (file)
@@ -729,14 +729,10 @@ static char *rna_path_rename_fix(ID *owner_id, const char *prefix, const char *o
                        DynStr *ds = BLI_dynstr_new();
                        const char *postfixPtr = oldNamePtr + oldNameLen;
                        char *newPath = NULL;
-                       char oldChar;
-                       
+
                        /* add the part of the string that goes up to the start of the prefix */
                        if (prefixPtr > oldpath) {
-                               oldChar = prefixPtr[0];
-                               prefixPtr[0] = 0;
-                               BLI_dynstr_append(ds, oldpath);
-                               prefixPtr[0] = oldChar;
+                               BLI_dynstr_nappend(ds, oldpath, prefixPtr - oldpath);
                        }
                        
                        /* add the prefix */
@@ -1613,7 +1609,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind
 }
 
 /* Simple replacement based data-setting of the FCurve using RNA */
-bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
+bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, float curval)
 {
        char *path = NULL;
        bool free_path = false;
@@ -1624,7 +1620,7 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
        
        /* write value to setting */
        if (path)
-               ok = animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
+               ok = animsys_write_rna_setting(ptr, path, fcu->array_index, curval);
        
        /* free temp path-info */
        if (free_path)
@@ -1647,8 +1643,8 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper
                if ((fcu->grp == NULL) || (fcu->grp->flag & AGRP_MUTED) == 0) {
                        /* check if this curve should be skipped */
                        if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
-                               calculate_fcurve(fcu, ctime);
-                               BKE_animsys_execute_fcurve(ptr, remap, fcu); 
+                               const float curval = calculate_fcurve(fcu, ctime);
+                               BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
                        }
                }
        }
@@ -1677,8 +1673,8 @@ static void animsys_evaluate_drivers(PointerRNA *ptr, AnimData *adt, float ctime
                                /* evaluate this using values set already in other places
                                 * NOTE: for 'layering' option later on, we should check if we should remove old value before adding
                                 *       new to only be done when drivers only changed */
-                               calculate_fcurve(fcu, ctime);
-                               ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu);
+                               const float curval = calculate_fcurve(fcu, ctime);
+                               ok = BKE_animsys_execute_fcurve(ptr, NULL, fcu, curval);
                                
                                /* clear recalc flag */
                                driver->flag &= ~DRIVER_FLAG_RECALC;
@@ -1746,8 +1742,8 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
        for (fcu = agrp->channels.first; (fcu) && (fcu->grp == agrp); fcu = fcu->next) {
                /* check if this curve should be skipped */
                if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) {
-                       calculate_fcurve(fcu, ctime);
-                       BKE_animsys_execute_fcurve(ptr, remap, fcu); 
+                       const float curval = calculate_fcurve(fcu, ctime);
+                       BKE_animsys_execute_fcurve(ptr, remap, fcu, curval);
                }
        }
 }
@@ -2878,8 +2874,8 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
                         * NOTE: for 'layering' option later on, we should check if we should remove old value before adding
                         *       new to only be done when drivers only changed */
                        //printf("\told val = %f\n", fcu->curval);
-                       calculate_fcurve(fcu, eval_ctx->ctime);
-                       ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu);
+                       const float curval = calculate_fcurve(fcu, eval_ctx->ctime);
+                       ok = BKE_animsys_execute_fcurve(&id_ptr, NULL, fcu, curval);
                        //printf("\tnew val = %f\n", fcu->curval);
 
                        /* clear recalc flag */
index d9462cd..bde06b0 100644 (file)
@@ -59,7 +59,10 @@ bool BKE_autoexec_match(const char *path)
        BLI_assert((U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0);
 
        for (path_cmp = U.autoexec_paths.first; path_cmp; path_cmp = path_cmp->next) {
-               if ((path_cmp->flag & USER_PATHCMP_GLOB)) {
+               if (path_cmp->path[0] == '\0') {
+                       /* pass */
+               }
+               else if ((path_cmp->flag & USER_PATHCMP_GLOB)) {
                        if (fnmatch(path_cmp->path, path, fnmatch_flags) == 0) {
                                return true;
                        }
index 31dac03..da78630 100644 (file)
@@ -852,7 +852,7 @@ int BKE_brush_size_get(const Scene *scene, const Brush *brush)
        UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
        int size = (ups->flag & UNIFIED_PAINT_SIZE) ? ups->size : brush->size;
        
-       return (int)((float)size * U.pixelsize);
+       return size;
 }
 
 int BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
index 5fba6c2..e30dbd7 100644 (file)
@@ -1402,6 +1402,24 @@ static void emDM_drawMappedFacesTex(
        emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
 }
 
+static void emdm_pass_attrib_update_uniforms(const DMVertexAttribs *attribs)
+{
+       int i;
+       if (attribs->totorco) {
+               glUniform1i(attribs->orco.gl_info_index, 0);
+       }
+       for (i = 0; i < attribs->tottface; i++) {
+               glUniform1i(attribs->tface[i].gl_info_index, 0);
+       }
+       for (i = 0; i < attribs->totmcol; i++) {
+               glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
+       }
+
+       for (i = 0; i < attribs->tottang; i++) {
+               glUniform1i(attribs->tang[i].gl_info_index, 0);
+       }
+}
+
 /**
  * \note
  *
@@ -1428,7 +1446,6 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
                        glTexCoord3fv(orco);
                else
                        glVertexAttrib3fv(attribs->orco.gl_index, orco);
-               glUniform1i(attribs->orco.gl_info_index, 0);
        }
        for (i = 0; i < attribs->tottface; i++) {
                const float *uv;
@@ -1445,7 +1462,6 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
                        glTexCoord2fv(uv);
                else
                        glVertexAttrib2fv(attribs->tface[i].gl_index, uv);
-               glUniform1i(attribs->tface[i].gl_info_index, 0);
        }
        for (i = 0; i < attribs->totmcol; i++) {
                float col[4];
@@ -1457,7 +1473,6 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
                        col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f;
                }
                glVertexAttrib4fv(attribs->mcol[i].gl_index, col);
-               glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
        }
 
        for (i = 0; i < attribs->tottang; i++) {
@@ -1469,7 +1484,6 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B
                        tang = zero;
                }
                glVertexAttrib4fv(attribs->tang[i].gl_index, tang);
-               glUniform1i(attribs->tang[i].gl_info_index, 0);
        }
 }
 
@@ -1526,6 +1540,7 @@ static void emDM_drawMappedFacesGLSL(
                        do_draw = setMaterial(matnr = new_matnr, &gattribs);
                        if (do_draw) {
                                DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
+                               emdm_pass_attrib_update_uniforms(&attribs);
                                if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) {
                                        BM_mesh_elem_index_ensure(bm, BM_LOOP);
                                }
index af5089f..787b915 100644 (file)
@@ -489,7 +489,9 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
 {
        int ret = 0;
 
-       if (eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) {
+       /* In case surface object is in Edit mode when loading the .blend, surface modifier is never executed
+        * and bvhtree never built, see T48415. */
+       if (eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd && eff->surmd->bvhtree) {
                /* closest point in the object surface is an effector */
                float vec[3];
 
index a2b5a05..395161a 100644 (file)
@@ -2671,7 +2671,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
 }
 
 /* Calculate the value of the given F-Curve at the given frame, and set its curval */
-void calculate_fcurve(FCurve *fcu, float ctime)
+float calculate_fcurve(FCurve *fcu, float evaltime)
 {
        /* only calculate + set curval (overriding the existing value) if curve has 
         * any data which warrants this...
@@ -2680,7 +2680,12 @@ void calculate_fcurve(FCurve *fcu, float ctime)
            list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE))
        {
                /* calculate and set curval (evaluates driver too if necessary) */
-               fcu->curval = evaluate_fcurve(fcu, ctime);
+               float curval = evaluate_fcurve(fcu, evaltime);
+               fcu->curval = curval;  /* debug display only, not thread safe! */
+               return curval;
+       }
+       else {
+               return 0.0f;
        }
 }
 
index b38b183..ea99fa8 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "BLT_translation.h"
 
+#include "BKE_library.h"
 #include "BKE_idcode.h"
 
 typedef struct {
@@ -54,6 +55,7 @@ typedef struct {
 /* plural need to match rna_main.c's MainCollectionDef */
 /* WARNING! Keep it in sync with i18n contexts in BLT_translation.h */
 static IDType idtypes[] = {
+       /** ID's directly below must all be in #Main, and be kept in sync with #MAX_LIBARRAY (membership, not order) */
        { ID_AC,   "Action",             "actions",         BLT_I18NCONTEXT_ID_ACTION,             IDTYPE_FLAGS_ISLINKABLE },
        { ID_AR,   "Armature",           "armatures",       BLT_I18NCONTEXT_ID_ARMATURE,           IDTYPE_FLAGS_ISLINKABLE },
        { ID_BR,   "Brush",              "brushes",         BLT_I18NCONTEXT_ID_BRUSH,              IDTYPE_FLAGS_ISLINKABLE },
@@ -61,7 +63,6 @@ static IDType idtypes[] = {
        { ID_CU,   "Curve",              "curves",          BLT_I18NCONTEXT_ID_CURVE,              IDTYPE_FLAGS_ISLINKABLE },
        { ID_GD,   "GPencil",            "grease_pencil",   BLT_I18NCONTEXT_ID_GPENCIL,            IDTYPE_FLAGS_ISLINKABLE }, /* rename gpencil */
        { ID_GR,   "Group",              "groups",          BLT_I18NCONTEXT_ID_GROUP,              IDTYPE_FLAGS_ISLINKABLE },
-       { ID_ID,   "ID",                 "ids",             BLT_I18NCONTEXT_ID_ID,                 0                       }, /* plural is fake */
        { ID_IM,   "Image",              "images",          BLT_I18NCONTEXT_ID_IMAGE,              IDTYPE_FLAGS_ISLINKABLE },
        { ID_IP,   "Ipo",                "ipos",            "",                                    IDTYPE_FLAGS_ISLINKABLE }, /* deprecated */
        { ID_KE,   "Key",                "shape_keys",      BLT_I18NCONTEXT_ID_SHAPEKEY,           0                       },
@@ -88,8 +89,14 @@ static IDType idtypes[] = {
        { ID_VF,   "VFont",              "fonts",           BLT_I18NCONTEXT_ID_VFONT,              IDTYPE_FLAGS_ISLINKABLE },
        { ID_WO,   "World",              "worlds",          BLT_I18NCONTEXT_ID_WORLD,              IDTYPE_FLAGS_ISLINKABLE },
        { ID_WM,   "WindowManager",      "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER,      0                       },
+
+       /** Keep last, not an ID exactly, only include for completeness */
+       { ID_ID,   "ID",                 "ids",             BLT_I18NCONTEXT_ID_ID,                 0                       }, /* plural is fake */
 };
 
+/* -1 for ID_ID */
+BLI_STATIC_ASSERT((ARRAY_SIZE(idtypes) - 1 == MAX_LIBARRAY), "Missing IDType");
+
 static IDType *idtype_from_name(const char *str) 
 {
        int i = ARRAY_SIZE(idtypes);
index 2eeb979..8df501b 100644 (file)
@@ -300,3 +300,10 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
 
        ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
 }
+
+void BKE_object_eval_proxy_backlink(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+{
+       if (ob->proxy) {
+               ob->proxy->proxy_from = ob;
+       }
+}
index d73f087..58ec75d 100644 (file)
@@ -637,6 +637,7 @@ void BKE_pbvh_free(PBVH *bvh)
                                BLI_gset_free(node->bm_other_verts, NULL);
                }
        }
+       GPU_free_pbvh_buffer_multires(&bvh->grid_common_gpu_buffer);
 
        if (bvh->deformed) {
                if (bvh->verts) {
@@ -1100,7 +1101,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
                                                                   node->totprim,
                                                                   bvh->grid_hidden,
                                                                   bvh->gridkey.grid_size,
-                                                                  &bvh->gridkey);
+                                                                  &bvh->gridkey, &bvh->grid_common_gpu_buffer);
                                        break;
                                case PBVH_FACES:
                                        node->draw_buffers =
index bae323d..4d2307c 100644 (file)
@@ -145,6 +145,11 @@ struct PBVH {
        const DMFlagMat *grid_flag_mats;
        int totgrid;
        BLI_bitmap **grid_hidden;
+       /* index_buf of GPU_PBVH_Buffers can be the same for all 'fully drawn' nodes (same size).
+        * Previously was stored in a static var in gpu_buffer.c, but this breaks in case we handle several different
+        * objects in sculpt mode with different sizes at the same time, so now storing that common gpu buffer
+        * in an opaque pointer per pbvh. See T47637. */
+       struct GridCommonGPUBuffer *grid_common_gpu_buffer;
 
        /* Only used during BVH build and update,
         * don't need to remain valid after */
index 0b5adab..06946e5 100644 (file)
@@ -441,7 +441,7 @@ static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info,
        gh->flag = flag;
 
        ghash_buckets_reset(gh, nentries_reserve);
-       gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 0, 64, BLI_MEMPOOL_NOP);
+       gh->entrypool = BLI_mempool_create(GHASH_ENTRY_SIZE(flag & GHASH_FLAG_IS_GSET), 64, 64, BLI_MEMPOOL_NOP);
 
        return gh;
 }
@@ -1287,7 +1287,7 @@ bool BLI_ghashutil_paircmp(const void *a, const void *b)
        const GHashPair *A = a;
        const GHashPair *B = b;
 
-       return (BLI_ghashutil_ptrcmp(A->first, B->first) &&
+       return (BLI_ghashutil_ptrcmp(A->first, B->first) ||
                BLI_ghashutil_ptrcmp(A->second, B->second));
 }
 
index 38d1575..b7a51f2 100644 (file)
@@ -605,19 +605,26 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
  */
 void *BLI_mempool_iterstep(BLI_mempool_iter *iter)
 {
-       BLI_freenode *ret;
+       if (UNLIKELY(iter->curchunk == NULL)) {
+               return NULL;
+       }
 
+       const unsigned int esize = iter->pool->esize;
+       BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex));
+       BLI_freenode *ret;
        do {
-               if (LIKELY(iter->curchunk)) {
-                       ret = (BLI_freenode *)(((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex));
+               ret = curnode;
+
+               if (++iter->curindex != iter->pool->pchunk) {
+                       curnode = POINTER_OFFSET(curnode, esize);
                }
                else {
-                       return NULL;
-               }
-
-               if (UNLIKELY(++iter->curindex == iter->pool->pchunk)) {
                        iter->curindex = 0;
                        iter->curchunk = iter->curchunk->next;
+                       if (iter->curchunk == NULL) {
+                               return NULL;
+                       }
+                       curnode = CHUNK_DATA(iter->curchunk);
                }
        } while (ret->freeword == FREEWORD);
 
index 7f657f4..9baccf3 100644 (file)
@@ -229,7 +229,9 @@ typedef struct BArrayInfo {
 
        /* pre-calculated */
        size_t chunk_byte_size;
+       /* min/max limits (inclusive) */
        size_t chunk_byte_size_min;
+       size_t chunk_byte_size_max;
 
        size_t accum_read_ahead_bytes;
 #ifdef USE_HASH_TABLE_ACCUMULATE
@@ -455,7 +457,7 @@ static void bchunk_list_ensure_min_size_last(
                if (MIN2(chunk_prev->data_len, chunk_curr->data_len) < info->chunk_byte_size_min) {
                        const size_t data_merge_len = chunk_prev->data_len + chunk_curr->data_len;
                        /* we could pass, but no need */
-                       if (data_merge_len <= (info->chunk_byte_size * BCHUNK_SIZE_MAX_MUL)) {
+                       if (data_merge_len <= info->chunk_byte_size_max) {
                                /* we have enough space to merge */
 
                                /* remove last from linklist */
@@ -527,6 +529,53 @@ static void bchunk_list_ensure_min_size_last(
 }
 #endif  /* USE_MERGE_CHUNKS */
 
+
+/**
+ * Split length into 2 values
+ * \param r_data_trim_len: Length which is aligned to the #BArrayInfo.chunk_byte_size
+ * \param r_data_last_chunk_len: The remaining bytes.
+ *
+ * \note This function ensures the size of \a r_data_last_chunk_len
+ * is larger than #BArrayInfo.chunk_byte_size_min.
+ */
+static void bchunk_list_calc_trim_len(
+        const BArrayInfo *info, const size_t data_len,
+        size_t *r_data_trim_len, size_t *r_data_last_chunk_len)
+{
+       size_t data_last_chunk_len = 0;
+       size_t data_trim_len = data_len;
+
+#ifdef USE_MERGE_CHUNKS
+       /* avoid creating too-small chunks
+        * more efficient then merging after */
+       if (data_len > info->chunk_byte_size) {
+               data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+               data_trim_len = data_trim_len - data_last_chunk_len;
+               if (data_last_chunk_len) {
+                       if (data_last_chunk_len < info->chunk_byte_size_min) {
+                               /* may be zero and thats OK */
+                               data_trim_len -= info->chunk_byte_size;
+                               data_last_chunk_len += info->chunk_byte_size;
+                       }
+               }
+       }
+       else {
+               data_trim_len = 0;
+               data_last_chunk_len = data_len;
+       }
+
+       BLI_assert((data_trim_len == 0) || (data_trim_len >= info->chunk_byte_size));
+#else
+       data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
+       data_trim_len = data_trim_len - data_last_chunk_len;
+#endif
+
+       BLI_assert(data_trim_len + data_last_chunk_len == data_len);
+
+       *r_data_trim_len = data_trim_len;
+       *r_data_last_chunk_len = data_last_chunk_len;
+}
+
 /**
  * Append and don't manage merging small chunks.
  */
@@ -542,14 +591,21 @@ static bool bchunk_list_append_only(
        return chunk;
 }
 
+/**
+ * \note This is for writing single chunks,
+ * use #bchunk_list_append_data_n when writing large blocks of memory into many chunks.
+ */
 static void bchunk_list_append_data(
         const BArrayInfo *info, BArrayMemory *bs_mem,
         BChunkList *chunk_list,
         const ubyte *data, const size_t data_len)
 {
        BLI_assert(data_len != 0);
+
        // printf("data_len: %d\n", data_len);
 #ifdef USE_MERGE_CHUNKS
+       BLI_assert(data_len <= info->chunk_byte_size_max);
+
        if (!BLI_listbase_is_empty(&chunk_list->chunk_refs)) {
                BChunkRef *cref = chunk_list->chunk_refs.last;
                BChunk *chunk_prev = cref->link;
@@ -589,6 +645,59 @@ static void bchunk_list_append_data(
 #endif
 }
 
+/**
+ * Similar to #bchunk_list_append_data, but handle multiple chunks.
+ * Use for adding arrays of arbitrary sized memory at once.
+ *
+ * \note This function takes care not to perform redundant chunk-merging checks,
+ * so we can write succesive fixed size chunks quickly.
+ */
+static void bchunk_list_append_data_n(
+        const BArrayInfo *info, BArrayMemory *bs_mem,
+        BChunkList *chunk_list,
+        const ubyte *data, size_t data_len)
+{
+       size_t data_trim_len, data_last_chunk_len;
+       bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
+
+       if (data_trim_len != 0) {
+               size_t i_prev;
+
+               {
+                       const size_t i = info->chunk_byte_size;
+                       bchunk_list_append_data(info, bs_mem, chunk_list, data, i);
+                       i_prev = i;
+               }
+
+               while (i_prev != data_trim_len) {
+                       const size_t i = i_prev + info->chunk_byte_size;
+                       BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev);
+                       bchunk_list_append_only(bs_mem, chunk_list, chunk);
+                       i_prev = i;
+               }
+
+               if (data_last_chunk_len) {
+                       BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], data_last_chunk_len);
+                       bchunk_list_append_only(bs_mem, chunk_list, chunk);
+                       // i_prev = data_len;  /* UNUSED */
+               }
+       }
+       else {
+               /* if we didn't write any chunks previously,
+                * we may need to merge with the last. */
+               if (data_last_chunk_len) {
+                       bchunk_list_append_data(info, bs_mem, chunk_list, data, data_last_chunk_len);
+                       // i_prev = data_len;  /* UNUSED */
+               }
+       }
+
+#ifdef USE_MERGE_CHUNKS
+       if (data_len > info->chunk_byte_size) {
+               BLI_assert(((BChunkRef *)chunk_list->chunk_refs.last)->link->data_len >= info->chunk_byte_size_min);
+       }
+#endif
+}
+
 static void bchunk_list_append(
         const BArrayInfo *info, BArrayMemory *bs_mem,
         BChunkList *chunk_list,
@@ -611,37 +720,11 @@ static void bchunk_list_fill_from_array(
 {
        BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
 
-       size_t data_last_chunk_len = 0;
-       size_t data_trim_len = data_len;
-
-#ifdef USE_MERGE_CHUNKS
-       /* avoid creating too-small chunks
-        * more efficient then merging after */
-       if (data_len > info->chunk_byte_size) {
-               data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
-               data_trim_len = data_trim_len - data_last_chunk_len;
-               if (data_last_chunk_len) {
-                       if (data_last_chunk_len < info->chunk_byte_size_min) {
-                               /* may be zero and thats OK */
-                               data_trim_len -= info->chunk_byte_size;
-                               data_last_chunk_len += info->chunk_byte_size;
-                       }
-               }
-       }
-       else {
-               data_trim_len = 0;
-               data_last_chunk_len = data_len;
-       }
-#else
-       data_last_chunk_len = (data_trim_len % info->chunk_byte_size);
-       data_trim_len = data_trim_len - data_last_chunk_len;
-#endif
-
-
-       BLI_assert(data_trim_len + data_last_chunk_len == data_len);
+       size_t data_trim_len, data_last_chunk_len;
+       bchunk_list_calc_trim_len(info, data_len, &data_trim_len, &data_last_chunk_len);
 
        size_t i_prev = 0;
-       while (i_prev < data_trim_len) {
+       while (i_prev != data_trim_len) {
                const size_t i = i_prev + info->chunk_byte_size;
                BChunk *chunk = bchunk_new_copydata(bs_mem, &data[i_prev], i - i_prev);
                bchunk_list_append_only(bs_mem, chunk_list, chunk);
@@ -1220,21 +1303,8 @@ static BChunkList *bchunk_list_from_data_merge(
                        if (cref_found != NULL) {
                                BLI_assert(i < data_len);
                                if (i != i_prev) {
-                                       size_t i_step = MIN2(i_prev + info->chunk_byte_size, data_len);
-                                       BLI_assert(i_step <= data_len);
-
-                                       while (i_prev != i) {
-                                               i_step = MIN2(i_step, i);
-                                               const ubyte  *data_slice = &data[i_prev];
-                                               const size_t  data_slice_len = i_step - i_prev;
-                                               /* First add all previous chunks! */
-                                               i_prev += data_slice_len;
-                                               bchunk_list_append_data(info, bs_mem, chunk_list, data_slice, data_slice_len);
-                                               BLI_assert(i_prev <= data_len);
-                                               ASSERT_CHUNKLIST_SIZE(chunk_list, i_prev);
-                                               ASSERT_CHUNKLIST_DATA(chunk_list, data);
-                                               i_step += info->chunk_byte_size;
-                                       }
+                                       bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
+                                       i_prev = i;
                                }
 
                                /* now add the reference chunk */
@@ -1294,14 +1364,9 @@ static BChunkList *bchunk_list_from_data_merge(
         *
         * Trailing chunks, no matches found in table lookup above.
         * Write all new data. */
-       BLI_assert(i_prev <= data_len);
-       while (i_prev != data_len) {
-               size_t i = i_prev + info->chunk_byte_size;
-               i = MIN2(i, data_len);
-               BLI_assert(i != i_prev);
-               bchunk_list_append_data(info, bs_mem, chunk_list, &data[i_prev], i - i_prev);
-               ASSERT_CHUNKLIST_DATA(chunk_list, data);
-               i_prev = i;
+       if (i_prev != data_len) {
+               bchunk_list_append_data_n(info, bs_mem, chunk_list, &data[i_prev], data_len - i_prev);
+               i_prev = data_len;
        }
 
        BLI_assert(i_prev == data_len);
@@ -1374,6 +1439,7 @@ BArrayStore *BLI_array_store_create(
        bs->info.chunk_byte_size = chunk_count * stride;
 #ifdef USE_MERGE_CHUNKS
        bs->info.chunk_byte_size_min = MAX2(1u, chunk_count / BCHUNK_SIZE_MIN_DIV) * stride;
+       bs->info.chunk_byte_size_max = (chunk_count * BCHUNK_SIZE_MAX_MUL) * stride;
 #endif
 
 #ifdef USE_HASH_TABLE_ACCUMULATE
@@ -1640,6 +1706,21 @@ bool BLI_array_store_is_valid(
                if (!(bchunk_list_size(chunk_list) == chunk_list->total_size)) {
                        return false;
                }
+
+               if (BLI_listbase_count(&chunk_list->chunk_refs) != (int)chunk_list->chunk_refs_len) {
+                       return false;
+               }
+
+#ifdef USE_MERGE_CHUNKS
+               /* ensure we merge all chunks that could be merged */
+               if (chunk_list->total_size > bs->info.chunk_byte_size_min) {
+                       for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
+                               if (cref->link->data_len < bs->info.chunk_byte_size_min) {
+                                       return false;
+                               }
+                       }
+               }
+#endif
        }
 
        {
index 76a16ed..a3b7962 100644 (file)
 /***/
 
 typedef struct OldNew {
-       void *old, *newp;
+       const void *old;
+       void *newp;
        int nr;
 } OldNew;
 
 typedef struct OldNewMap {
        OldNew *entries;
        int nentries, entriessize;
-       int sorted;
+       bool sorted;
        int lasthit;
 } OldNewMap;
 
@@ -285,12 +286,13 @@ static int verg_oldnewmap(const void *v1, const void *v2)
 
 static void oldnewmap_sort(FileData *fd) 
 {
+       BLI_assert(fd->libmap->sorted == false);
        qsort(fd->libmap->entries, fd->libmap->nentries, sizeof(OldNew), verg_oldnewmap);
        fd->libmap->sorted = 1;
 }
 
 /* nr is zero for data, and ID code for libdata */
-static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr) 
+static void oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
 {
        OldNew *entry;
        
@@ -307,7 +309,7 @@ static void oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int n
        entry->nr = nr;
 }
 
-void blo_do_versions_oldnewmap_insert(OldNewMap *onm, void *oldaddr, void *newaddr, int nr)
+void blo_do_versions_oldnewmap_insert(OldNewMap *onm, const void *oldaddr, void *newaddr, int nr)
 {
        oldnewmap_insert(onm, oldaddr, newaddr, nr);
 }
@@ -362,7 +364,7 @@ static int oldnewmap_lookup_entry_full(const OldNewMap *onm, const void *addr, i
        return -1;
 }
 
-static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr, bool increase_users) 
+static void *oldnewmap_lookup_and_inc(OldNewMap *onm, const void *addr, bool increase_users)
 {
        int i;
        
@@ -392,7 +394,7 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr, bool increase_
 }
 
 /* for libdata, nr has ID code, no increment */
-static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
+static void *oldnewmap_liblookup(OldNewMap *onm, const void *addr, const void *lib)
 {
        if (addr == NULL) {
                return NULL;
@@ -400,11 +402,8 @@ static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib)
 
        /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */
        if (onm->sorted) {
-               OldNew entry_s, *entry;
-
-               entry_s.old = addr;
-
-               entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
+               const OldNew entry_s = {.old = addr};
+               OldNew *entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap);
                if (entry) {
                        ID *id = entry->newp;
 
@@ -484,53 +483,57 @@ void blo_join_main(ListBase *mainlist)
        }
 }
 
-static void split_libdata(ListBase *lb, Main *first)
+static void split_libdata(ListBase *lb_src, Main **lib_main_array, const unsigned int lib_main_array_len)
 {
-       ListBase *lbn;
-       ID *id, *idnext;
-       Main *mainvar;
-       
-       id = lb->first;
-       while (id) {
+       for (ID *id = lb_src->first, *idnext; id; id = idnext) {
                idnext = id->next;
+
                if (id->lib) {
-                       mainvar = first;
-                       while (mainvar) {
-                               if (mainvar->curlib == id->lib) {
-                                       lbn= which_libbase(mainvar, GS(id->name));
-                                       BLI_remlink(lb, id);
-                                       BLI_addtail(lbn, id);
-                                       break;
-                               }
-                               mainvar = mainvar->next;
+                       if (((unsigned int)id->lib->temp_index < lib_main_array_len) &&
+                           /* this check should never fail, just incase 'id->lib' is a dangling pointer. */
+                           (lib_main_array[id->lib->temp_index]->curlib == id->lib))
+                       {
+                               Main *mainvar = lib_main_array[id->lib->temp_index];
+                               ListBase *lb_dst = which_libbase(mainvar, GS(id->name));
+                               BLI_remlink(lb_src, id);
+                               BLI_addtail(lb_dst, id);
+                       }
+                       else {
+                               printf("%s: invalid library for '%s'\n", __func__, id->name);
+                               BLI_assert(0);
                        }
-                       if (mainvar == NULL) printf("error split_libdata\n");
                }
-               id = idnext;
        }
 }
 
 void blo_split_main(ListBase *mainlist, Main *main)
 {
-       ListBase *lbarray[MAX_LIBARRAY];
-       Library *lib;
-       int i;
-       
        mainlist->first = mainlist->last = main;
        main->next = NULL;
        
        if (BLI_listbase_is_empty(&main->library))
                return;
        
-       for (lib = main->library.first; lib; lib = lib->id.next) {
+       /* (Library.temp_index -> Main), lookup table */
+       const unsigned int lib_main_array_len = BLI_listbase_count(&main->library);
+       Main             **lib_main_array     = MEM_mallocN(lib_main_array_len * sizeof(*lib_main_array), __func__);
+
+       int i = 0;
+       for (Library *lib = main->library.first; lib; lib = lib->id.next, i++) {
                Main *libmain = BKE_main_new();
                libmain->curlib = lib;
                BLI_addtail(mainlist, libmain);
+               lib->temp_index = i;
+               lib_main_array[i] = libmain;
        }
        
+       ListBase *lbarray[MAX_LIBARRAY];
        i = set_listbasepointers(main, lbarray);
-       while (i--)
-               split_libdata(lbarray[i], main->next);
+       while (i--) {
+               split_libdata(lbarray[i], lib_main_array, lib_main_array_len);
+       }
+
+       MEM_freeN(lib_main_array);
 }
 
 static void read_file_version(FileData *fd, Main *main)
@@ -1411,7 +1414,7 @@ BlendThumbnail *BLO_thumbnail_from_file(const char *filepath)
 
 /* ************** OLD POINTERS ******************* */
 
-static void *newdataadr(FileData *fd, void *adr)               /* only direct databocks */
+static void *newdataadr(FileData *fd, const void *adr)         /* only direct databocks */
 {
        return oldnewmap_lookup_and_inc(fd->datamap, adr, true);
 }
@@ -1428,7 +1431,7 @@ static void *newdataadr(FileData *fd, void *adr)          /* only direct databocks */
  * fcurve group pointer and keeps lasthit optimal for linking all further
  * fcurves.
  */
-static void *newdataadr_ex(FileData *fd, void *adr, bool increase_lasthit)             /* only direct databocks */
+static void *newdataadr_ex(FileData *fd, const void *adr, bool increase_lasthit)               /* only direct databocks */
 {
        if (increase_lasthit) {
                return newdataadr(fd, adr);
@@ -1441,38 +1444,38 @@ static void *newdataadr_ex(FileData *fd, void *adr, bool increase_lasthit)              /* o
        }
 }
 
-static void *newdataadr_no_us(FileData *fd, void *adr)         /* only direct databocks */
+static void *newdataadr_no_us(FileData *fd, const void *adr)           /* only direct databocks */
 {
        return oldnewmap_lookup_and_inc(fd->datamap, adr, false);
 }
 
-static void *newglobadr(FileData *fd, void *adr)           /* direct datablocks with global linking */
+static void *newglobadr(FileData *fd, const void *adr)     /* direct datablocks with global linking */
 {
        return oldnewmap_lookup_and_inc(fd->globmap, adr, true);
 }
 
-static void *newimaadr(FileData *fd, void *adr)                    /* used to restore image data after undo */
+static void *newimaadr(FileData *fd, const void *adr)              /* used to restore image data after undo */
 {
        if (fd->imamap && adr)
                return oldnewmap_lookup_and_inc(fd->imamap, adr, true);
        return NULL;
 }
 
-static void *newmclipadr(FileData *fd, void *adr)      /* used to restore movie clip data after undo */
+static void *newmclipadr(FileData *fd, const void *adr)      /* used to restore movie clip data after undo */
 {
        if (fd->movieclipmap && adr)
                return oldnewmap_lookup_and_inc(fd->movieclipmap, adr, true);
        return NULL;
 }
 
-static void *newsoundadr(FileData *fd, void *adr)      /* used to restore sound data after undo */
+static void *newsoundadr(FileData *fd, const void *adr)      /* used to restore sound data after undo */
 {
        if (fd->soundmap && adr)
                return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
        return NULL;
 }
 
-static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packed data after undo */
+static void *newpackedadr(FileData *fd, const void *adr)      /* used to restore packed data after undo */
 {
        if (fd->packedmap && adr)
                return oldnewmap_lookup_and_inc(fd->packedmap, adr, true);
@@ -1481,17 +1484,17 @@ static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packe
 }
 
 
-static void *newlibadr(FileData *fd, void *lib, void *adr)             /* only lib data */
+static void *newlibadr(FileData *fd, const void *lib, const void *adr)         /* only lib data */
 {
        return oldnewmap_liblookup(fd->libmap, adr, lib);
 }
 
-void *blo_do_versions_newlibadr(FileData *fd, void *lib, void *adr)            /* only lib data */
+void *blo_do_versions_newlibadr(FileData *fd, const void *lib, const void *adr)                /* only lib data */
 {
        return newlibadr(fd, lib, adr);
 }
 
-static void *newlibadr_us(FileData *fd, void *lib, void *adr)  /* increases user number */
+static void *newlibadr_us(FileData *fd, const void *lib, const void *adr)      /* increases user number */
 {
        ID *id = newlibadr(fd, lib, adr);
        
@@ -1500,15 +1503,18 @@ static void *newlibadr_us(FileData *fd, void *lib, void *adr)   /* increases user
        return id;
 }
 
-void *blo_do_versions_newlibadr_us(FileData *fd, void *lib, void *adr) /* increases user number */
+void *blo_do_versions_newlibadr_us(FileData *fd, const void *lib, const void *adr)     /* increases user number */
 {
        return newlibadr_us(fd, lib, adr);
 }
 
-static void change_idid_adr_fd(FileData *fd, void *old, void *new)
+static void change_idid_adr_fd(FileData *fd, const void *old, void *new)
 {
        int i;
        
+       /* use a binary search if we have a sorted libmap, for now it's not needed. */
+       BLI_assert(fd->libmap->sorted == false);
+
        for (i = 0; i < fd->libmap->nentries; i++) {
                OldNew *entry = &fd->libmap->entries[i];
                
@@ -7496,7 +7502,7 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a
        return bhead;
 }
 
-static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID **r_id)
+static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const short tag, ID **r_id)
 {
        /* this routine reads a libblock and its direct data. Use link functions to connect it all
         */
@@ -7508,8 +7514,8 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        /* In undo case, most libs and linked data should be kept as is from previous state (see BLO_read_from_memfile).
         * However, some needed by the snapshot being read may have been removed in previous one, and would go missing.
         * This leads e.g. to desappearing objects in some undo/redo case, see T34446.
-     * That means we have to carefully check whether current lib or libdata already exits in old main, if it does
-     * we merely copy it over into new main area, otherwise we have to do a full read of that bhead... */
+        * That means we have to carefully check whether current lib or libdata already exits in old main, if it does
+        * we merely copy it over into new main area, otherwise we have to do a full read of that bhead... */
        if (fd->memfile && ELEM(bhead->code, ID_LI, ID_ID)) {
                const char *idname = bhead_id_name(fd, bhead);
 
@@ -7582,7 +7588,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID
        if (!id)
                return blo_nextbhead(fd, bhead);
        
-       id->tag = flag | LIB_TAG_NEED_LINK;
+       id->tag = tag | LIB_TAG_NEED_LINK;
        id->lib = main->curlib;
        id->us = ID_FAKE_USERS(id);
        id->icon_id = 0;
@@ -9229,7 +9235,7 @@ static void give_base_to_groups(
        }
 }
 
-static ID *create_placeholder(Main *mainvar, const char *idname, const short flag)
+static ID *create_placeholder(Main *mainvar, const char *idname, const short tag)
 {
        const short idcode = GS(idname);
        ListBase *lb = which_libbase(mainvar, idcode);
@@ -9238,7 +9244,7 @@ static ID *create_placeholder(Main *mainvar, const char *idname, const short fla
        memcpy(ph_id->name, idname, sizeof(ph_id->name));
        BKE_libblock_init_empty(ph_id);
        ph_id->lib = mainvar->curlib;
-       ph_id->tag = flag | LIB_TAG_MISSING;
+       ph_id->tag = tag | LIB_TAG_MISSING;
        ph_id->us = ID_FAKE_USERS(ph_id);
        ph_id->icon_id = 0;
 
@@ -9577,21 +9583,22 @@ void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
 
 /* ************* READ LIBRARY ************** */
 
-static int mainvar_count_libread_blocks(Main *mainvar)
+static int mainvar_id_tag_any_check(Main *mainvar, const short tag)
 {
        ListBase *lbarray[MAX_LIBARRAY];
-       int a, tot = 0;
+       int a;
        
        a = set_listbasepointers(mainvar, lbarray);
        while (a--) {
                ID *id;
                
                for (id = lbarray[a]->first; id; id = id->next) {
-                       if (id->tag & LIB_TAG_READ)
-                               tot++;
+                       if (id->tag & tag) {
+                               return true;
+                       }
                }
        }
-       return tot;
+       return false;
 }
 
 static void read_libraries(FileData *basefd, ListBase *mainlist)
@@ -9611,10 +9618,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
                /* test 1: read libdata */
                mainptr= mainl->next;
                while (mainptr) {
-                       int tot = mainvar_count_libread_blocks(mainptr);
-                       
-                       // printf("found LIB_TAG_READ %s\n", mainptr->curlib->name);
-                       if (tot) {
+                       if (mainvar_id_tag_any_check(mainptr, LIB_TAG_READ)) {
+                               // printf("found LIB_TAG_READ %s\n", mainptr->curlib->name);
+
                                FileData *fd = mainptr->curlib->filedata;
                                
                                if (fd == NULL) {
index f5c19f5..42728fd 100644 (file)
@@ -156,9 +156,9 @@ const char *bhead_id_name(const FileData *fd, const BHead *bhead);
 
 void blo_reportf_wrap(struct ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4);
 
-void blo_do_versions_oldnewmap_insert(struct OldNewMap *onm, void *oldaddr, void *newaddr, int nr);
-void *blo_do_versions_newlibadr(struct FileData *fd, void *lib, void *adr);
-void *blo_do_versions_newlibadr_us(struct FileData *fd, void *lib, void *adr);
+void blo_do_versions_oldnewmap_insert(struct OldNewMap *onm, const void *oldaddr, void *newaddr, int nr);
+void *blo_do_versions_newlibadr(struct FileData *fd, const void *lib, const void *adr);
+void *blo_do_versions_newlibadr_us(struct FileData *fd, const void *lib, const void *adr);
 
 struct PartEff *blo_do_version_give_parteff_245(struct Object *ob);
 void blo_do_version_old_trackto_to_constraints(struct Object *ob);
index d6f0754..d631e15 100644 (file)
@@ -1107,9 +1107,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                                }
                        }
                }
-       }
 
-       {
                for (Camera *camera = main->camera.first; camera != NULL; camera = camera->id.next) {
                        if (camera->stereo.pole_merge_angle_from == 0.0f &&
                            camera->stereo.pole_merge_angle_to == 0.0f)
@@ -1118,5 +1116,19 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                                camera->stereo.pole_merge_angle_to = DEG2RAD(75.0f);
                        }
                }
+
+               if (!DNA_struct_elem_find(fd->filesdna, "NormalEditModifierData", "float", "mix_limit")) {
+                       Object *ob;
+
+                       for (ob = main->object.first; ob; ob = ob->id.next) {
+                               ModifierData *md;
+                               for (md = ob->modifiers.first; md; md = md->next) {
+                                       if (md->type == eModifierType_NormalEdit) {
+                                               NormalEditModifierData *nemd = (NormalEditModifierData *)md;
+                                               nemd->mix_limit = DEG2RADF(180.0f);
+                                       }
+                               }
+                       }
+               }
        }
 }
index f7e3622..0ed1dff 100644 (file)
@@ -198,6 +198,12 @@ typedef struct BevelParams {
 
 // #include "bevdebug.c"
 
+/* some flags to re-enable old behavior for a while, in case fixes broke things not caught by regression tests */
+static int bev_debug_flags = 0;
+#define DEBUG_OLD_PLANE_SPECIAL (bev_debug_flags & 1)
+#define DEBUG_OLD_PROJ_TO_PERP_PLANE (bev_debug_flags & 2)
+#define DEBUG_OLD_FLAT_MID (bev_debug_flags & 4)
+
 /* Make a new BoundVert of the given kind, insert it at the end of the circular linked
  * list with entry point bv->boundstart, and return it. */
 static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@@ -1045,15 +1051,21 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
                sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
                normalize_v3(pro->proj_dir);
                project_to_edge(e->e, co1, co2, pro->midco);
-               /* put arc endpoints on plane with normal proj_dir, containing midco */
-               add_v3_v3v3(co3, co1, pro->proj_dir);
-               if (!isect_line_plane_v3(pro->coa, co1, co3, pro->midco, pro->proj_dir)) {
-                       /* shouldn't happen */
-                       copy_v3_v3(pro->coa, co1);
+               if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
+                       /* put arc endpoints on plane with normal proj_dir, containing midco */
+                       add_v3_v3v3(co3, co1, pro->proj_dir);
+                       if (!isect_line_plane_v3(pro->coa, co1, co3, pro->midco, pro->proj_dir)) {
+                               /* shouldn't happen */
+                               copy_v3_v3(pro->coa, co1);
+                       }
+                       add_v3_v3v3(co3, co2, pro->proj_dir);
+                       if (!isect_line_plane_v3(pro->cob, co2, co3, pro->midco, pro->proj_dir)) {
+                               /* shouldn't happen */
+                               copy_v3_v3(pro->cob, co2);
+                       }
                }
-               add_v3_v3v3(co3, co2, pro->proj_dir);
-               if (!isect_line_plane_v3(pro->cob, co2, co3, pro->midco, pro->proj_dir)) {
-                       /* shouldn't happen */
+               else {
+                       copy_v3_v3(pro->coa, co1);
                        copy_v3_v3(pro->cob, co2);
                }
                /* default plane to project onto is the one with triangle co1 - midco - co2 in it */
@@ -1066,19 +1078,48 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
                if (l  <= BEVEL_EPSILON_BIG) {
                        /* co1 - midco -co2 are collinear.
                         * Should be case that beveled edge is coplanar with two boundary verts.
+                        * We want to move the profile to that common plane, if possible.
+                        * That makes the multi-segment bevels curve nicely in that plane, as users expect.
+                        * The new midco should be either v (when neighbor edges are unbeveled)
+                        * or the intersection of the offset lines (if they are).
                         * If the profile is going to lead into unbeveled edges on each side
                         * (that is, both BoundVerts are "on-edge" points on non-beveled edges)
-                        * then in order to get curve in multi-segment case, change projection plane
-                        * to be that common plane, projection dir to be the plane normal,
-                        * and mid to be the original vertex.
-                        * Otherwise, we just want to linearly interpolate between co1 and co2.
                         */
-                       if (e->prev->is_bev || e->next->is_bev) {
+                       if (DEBUG_OLD_PLANE_SPECIAL && (e->prev->is_bev || e->next->is_bev)) {
                                do_linear_interp = true;
                        }
                        else {
-                               copy_v3_v3(pro->coa, co1);
-                               copy_v3_v3(pro->midco, bv->v->co);
+                               if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
+                                       copy_v3_v3(pro->coa, co1);
+                                       copy_v3_v3(pro->cob, co2);
+                               }
+                               if (DEBUG_OLD_FLAT_MID) {
+                                       copy_v3_v3(pro->midco, bv->v->co);
+                               }
+                               else {
+                                       copy_v3_v3(pro->midco, bv->v->co);
+                                       if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
+                                               /* want mid at the meet point of next and prev offset edges */
+                                               float d3[3], d4[3], co4[3], meetco[3], isect2[3];
+                                               int isect_kind;
+
+                                               sub_v3_v3v3(d3, e->prev->e->v1->co, e->prev->e->v2->co);
+                                               sub_v3_v3v3(d4, e->next->e->v1->co, e->next->e->v2->co);
+                                               normalize_v3(d3);
+                                               normalize_v3(d4);
+                                               add_v3_v3v3(co3, co1, d3);
+                                               add_v3_v3v3(co4, co2, d4);
+                                               isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
+                                               if (isect_kind != 0) {
+                                                       copy_v3_v3(pro->midco, meetco);
+                                               }
+                                               else {
+                                                       /* offset lines are collinear - want linear interpolation */
+                                                       mid_v3_v3v3(pro->midco, co1, co2);
+                                                       do_linear_interp = true;
+                                               }
+                                       }
+                               }
                                copy_v3_v3(pro->cob, co2);
                                sub_v3_v3v3(d1, pro->midco, co1);
                                normalize_v3(d1);
@@ -3436,7 +3477,7 @@ static bool fast_bevel_edge_order(BevVert *bv)
                        }
                }
                if (nsucs == 0 || (nsucs == 2 && j != 1) || nsucs > 2 ||
-                       (j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e)))
+                   (j == bv->edgecount - 1 && !edges_face_connected_at_vert(bmenext, bv->edges[0].e)))
                {
                        for (k = 1; k < j; k++) {
                                BM_BEVEL_EDGE_TAG_DISABLE(bv->edges[k].e);
@@ -3868,7 +3909,7 @@ static bool bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f)
                                        /* going cw */
                                        if (vm->seg > 1) {
                                                if (vm->mesh_kind == M_ADJ || bp->vertex_only ||
-                                                       (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev))
+                                                   (vm->mesh_kind == M_NONE && v->ebev != e && v->ebev != eprev))
                                                {
                                                        i = v->prev->index;
                                                        for (k = vm->seg - 1; k > 0; k--) {
index fca9b9f..1bc2bff 100644 (file)
@@ -107,27 +107,39 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
        std::vector<COLLADAFW::Node *>::iterator it;
        it = std::find(finished_joints.begin(), finished_joints.end(), node);
        if (it != finished_joints.end()) return chain_length;
-
-       // JointData* jd = get_joint_data(node);
        
-       // TODO rename from Node "name" attrs later
        EditBone *bone = ED_armature_edit_bone_add(arm, (char *)bc_get_joint_name(node));
        totbone++;
 
-       if (skin && skin->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
-               // get original world-space matrix
-               invert_m4_m4(mat, joint_inv_bind_mat);
+       /*
+        * We use the inv_bind_shape matrix to apply the armature bind pose as its rest pose.
+       */
+
+       std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it;
+       bool bone_is_not_skinned = true;
+       for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) {
+
+               SkinInfo *b = &skin_it->second;
+               if (b->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
 
-               // And make local to armature
-               Object *ob_arm = skin->BKE_armature_from_object();
-               if (ob_arm) {
-                       float invmat[4][4];
-                       invert_m4_m4(invmat, ob_arm->obmat);
-                       mul_m4_m4m4(mat, invmat, mat);
+                       // get original world-space matrix
+                       invert_m4_m4(mat, joint_inv_bind_mat);
+
+                       // And make local to armature
+                       Object *ob_arm = skin->BKE_armature_from_object();
+                       if (ob_arm) {
+                               float invmat[4][4];
+                               invert_m4_m4(invmat, ob_arm->obmat);
+                               mul_m4_m4m4(mat, invmat, mat);
+                       }
+
+                       bone_is_not_skinned = false;
+                       break;
                }
        }
+
        // create a bone even if there's no joint data for it (i.e. it has no influence)
-       else {
+       if (bone_is_not_skinned) {
                float obmat[4][4];
                // bone-space
                get_node_mat(obmat, node, NULL, NULL);
@@ -145,7 +157,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
 
        float loc[3], size[3], rot[3][3]; 
 
-       BoneExtended &be = add_bone_extended(bone, node, layer_labels);
+       BoneExtended &be = add_bone_extended(bone, node, totchild, layer_labels);
        int layer = be.get_bone_layers();
        if (layer) bone->layer = layer;
        arm->layer |= layer; // ensure that all populated bone layers are visible after import
@@ -168,7 +180,6 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
                mat4_to_loc_rot_size(loc, rot, size, mat);
                mat3_to_vec_roll(rot, NULL, &angle);
        }
-
        copy_v3_v3(bone->head, mat[3]);
        add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
 
@@ -434,12 +445,12 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm)
        return armature_joints.back();
 }
 #endif
-void ArmatureImporter::create_armature_bones( )
+Object *ArmatureImporter::create_armature_bones(std::vector<Object *> &ob_arms)
 {
        std::vector<COLLADAFW::Node *>::iterator ri;
        std::vector<std::string> layer_labels;
+       Object *ob_arm = NULL;
 
-       leaf_bone_length = FLT_MAX;
        //if there is an armature created for root_joint next root_joint
        for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
                if (get_armature_for_joint(*ri) != NULL) continue;
@@ -467,34 +478,21 @@ void ArmatureImporter::create_armature_bones( )
                create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels);
 
                /* exit armature edit mode to populate the Armature object */
+               unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
                ED_armature_from_edit(armature);
                ED_armature_edit_free(armature);
 
-               /* and step back to edit mode to fix the leaf nodes */
-               ED_armature_to_edit(armature);
-
-               if (this->import_settings->fix_orientation || this->import_settings->find_chains) {
-
-                       if (this->import_settings->find_chains)
-                               connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
-
-                       if (this->import_settings->fix_orientation)
-                               fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
-
-                       // exit armature edit mode
-                       unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
+               int index = std::find(ob_arms.begin(), ob_arms.end(), ob_arm) - ob_arms.begin();
+               if (index == 0) {
+                       ob_arms.push_back(ob_arm);
                }
 
-               fix_parent_connect(armature, (Bone *)armature->bonebase.first);
-
-               ED_armature_from_edit(armature);
-               ED_armature_edit_free(armature);
-
                DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
        }
+       return ob_arm;
 }
 
-void ArmatureImporter::create_armature_bones(SkinInfo& skin)
+Object *ArmatureImporter::create_armature_bones(SkinInfo& skin)
 {
        // just do like so:
        // - get armature
@@ -590,7 +588,6 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
 
        totbone = 0;
        // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
-       leaf_bone_length = FLT_MAX;
 
        // create bones
        /*
@@ -606,6 +603,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
 
                // since root_joints may contain joints for multiple controllers, we need to filter
                if (skin.uses_joint_or_descendant(*ri)) {
+
                        create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, armature, layer_labels);
 
                        if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
@@ -617,18 +615,9 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
        ED_armature_from_edit(armature);
        ED_armature_edit_free(armature);
 
-       /* and step back to edit mode to fix the leaf nodes */
-       ED_armature_to_edit(armature);
-
-       if (armature->bonebase.first) {
-               /* Do this only if Armature has bones */
-               //connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
-               //fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
-       }
-       // exit armature edit mode
-       ED_armature_from_edit(armature);
-       ED_armature_edit_free(armature);
        DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
+
+       return ob_arm;
 }
 
 void ArmatureImporter::set_pose(Object *ob_arm,  COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4])
@@ -703,22 +692,42 @@ void ArmatureImporter::add_root_joint(COLLADAFW::Node *node)
 #endif
 
 // here we add bones to armatures, having armatures previously created in write_controller
-void ArmatureImporter::make_armatures(bContext *C)
+void ArmatureImporter::make_armatures(bContext *C, std::vector<Object *> &objects_to_scale)
 {
+       std::vector<Object *> ob_arms;
        std::map<COLLADAFW::UniqueId, SkinInfo>::iterator it;
+
+       leaf_bone_length = FLT_MAX; /*TODO: Make this work for more than one armature in the import file*/
+
        for (it = skin_by_data_uid.begin(); it != skin_by_data_uid.end(); it++) {
 
                SkinInfo& skin = it->second;
 
-               create_armature_bones(skin);
+               Object *ob_arm = create_armature_bones(skin);
 
                // link armature with a mesh object
                const COLLADAFW::UniqueId &uid = skin.get_controller_uid();
                const COLLADAFW::UniqueId *guid = get_geometry_uid(uid);
                if (guid != NULL) {
                        Object *ob = mesh_importer->get_object_by_geom_uid(*guid);
-                       if (ob)
+                       if (ob) {
                                skin.link_armature(C, ob, joint_by_uid, this);
+
+                               std::vector<Object *>::iterator ob_it = std::find(objects_to_scale.begin(), objects_to_scale.end(), ob);
+
+                               if (ob_it != objects_to_scale.end()) {
+                                       int index = ob_it - objects_to_scale.begin();
+                                       objects_to_scale.erase(objects_to_scale.begin() + index);
+                               }
+
+                               if (std::find(objects_to_scale.begin(), objects_to_scale.end(), ob_arm) == objects_to_scale.end()) {
+                                       objects_to_scale.push_back(ob_arm);
+                               }
+
+                               if (std::find(ob_arms.begin(), ob_arms.end(), ob_arm) == ob_arms.end()) {
+                                       ob_arms.push_back(ob_arm);
+                               }
+                       }
                        else
                                fprintf(stderr, "Cannot find object to link armature with.\n");
                }
@@ -735,7 +744,35 @@ void ArmatureImporter::make_armatures(bContext *C)
        }
        
        //for bones without skins
-       create_armature_bones();
+       create_armature_bones(ob_arms);
+
+       // Fix bone relations
+       std::vector<Object *>::iterator ob_arm_it;
+       for (ob_arm_it = ob_arms.begin(); ob_arm_it != ob_arms.end(); ob_arm_it++) {
+
+               Object *ob_arm = *ob_arm_it;
+               bArmature *armature = (bArmature *)ob_arm->data;
+
+               /* and step back to edit mode to fix the leaf nodes */
+               ED_armature_to_edit(armature);
+
+               if (this->import_settings->fix_orientation || this->import_settings->find_chains) {
+
+                       if (this->import_settings->find_chains)
+                               connect_bone_chains(armature, (Bone *)armature->bonebase.first, UNLIMITED_CHAIN_MAX);
+
+                       if (this->import_settings->fix_orientation)
+                               fix_leaf_bones(armature, (Bone *)armature->bonebase.first);
+
+                       // exit armature edit mode
+
+               }
+
+               fix_parent_connect(armature, (Bone *)armature->bonebase.first);
+
+               ED_armature_from_edit(armature);
+               ED_armature_edit_free(armature);
+       }
 }
 
 #if 0
@@ -922,7 +959,7 @@ bool ArmatureImporter::get_joint_bind_mat(float m[4][4], COLLADAFW::Node *joint)
        return found;
 }
 
-BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, std::vector<std::string> &layer_labels)
+BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Node *node, int sibcount, std::vector<std::string> &layer_labels)
 {
        BoneExtended *be = new BoneExtended(bone);
        extended_bones[bone->name] = be;
@@ -930,11 +967,14 @@ BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Nod
        TagsMap::iterator etit;
        ExtraTags *et = 0;
        etit = uid_tags_map.find(node->getUniqueId().toAscii());
+
+       bool has_connect = false;
+       int connect_type = -1;
+
        if (etit != uid_tags_map.end()) {
 
                float tail[3] = { FLT_MAX, FLT_MAX, FLT_MAX };
                float roll = 0;
-               int use_connect = -1;
                std::string layers;
 
                et = etit->second;
@@ -944,21 +984,29 @@ BoneExtended &ArmatureImporter::add_bone_extended(EditBone *bone, COLLADAFW::Nod
                has_tail |= et->setData("tip_y", &tail[1]);
                has_tail |= et->setData("tip_z", &tail[2]);
 
-               bool has_connect = et->setData("connect", &use_connect);
-               bool has_roll    = et->setData("roll", &roll);
+               has_connect   = et->setData("connect", &connect_type);
+               bool has_roll = et->setData("roll", &roll);
                
                layers = et->setData("layer", layers);
 
                if (has_tail && !has_connect)
                {
-                       use_connect = 0; // got a bone tail definition but no connect info -> bone is not connected
+                       /* got a bone tail definition but no connect info -> bone is not connected */
+                       has_connect  = true;
+                       connect_type = 0; 
                }
 
                be->set_bone_layers(layers, layer_labels);
                if (has_tail) be->set_tail(tail);
                if (has_roll) be->set_roll(roll);
-               be->set_use_connect(use_connect);
        }
+
+       if (!has_connect && this->import_settings->auto_connect) {
+               /* auto connect only whyen parent has exactly one child*/
+               connect_type = sibcount == 1;
+       }
+
+       be->set_use_connect(connect_type);
        be->set_leaf_bone(true);
 
        return *be;
index f38bd1a..e006ccb 100644 (file)
@@ -108,7 +108,7 @@ private:
        int create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
                float parent_mat[4][4], bArmature *arm, std::vector<std::string> &layer_labels);
 
-       BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, std::vector<std::string> &layer_labels);
+       BoneExtended &add_bone_extended(EditBone *bone, COLLADAFW::Node * node, int sibcount, std::vector<std::string> &layer_labels);
        void clear_extended_boneset();
 
        void fix_leaf_bones(bArmature *armature, Bone *bone);
@@ -131,8 +131,8 @@ private:
        ArmatureJoints& get_armature_joints(Object *ob_arm);
 #endif
 
-       void create_armature_bones(SkinInfo& skin);
-       void create_armature_bones( );
+       Object *create_armature_bones(SkinInfo& skin);
+       Object *create_armature_bones(std::vector<Object *> &arm_objs);
 
        /** TagsMap typedef for uid_tags_map. */
        typedef std::map<std::string, ExtraTags*> TagsMap;
@@ -145,7 +145,7 @@ public:
        void add_root_joint(COLLADAFW::Node *node, Object *parent);
 
        // here we add bones to armatures, having armatures previously created in write_controller
-       void make_armatures(bContext *C);
+       void make_armatures(bContext *C, std::vector<Object *> &objects_to_scale);
 
        void make_shape_keys();
 
index 45dcf43..3a709da 100644 (file)
@@ -239,7 +239,7 @@ void DocumentImporter::finish()
        mesh_importer.optimize_material_assignements();
 
        armature_importer.set_tags_map(this->uid_tags_map);
-       armature_importer.make_armatures(mContext);
+       armature_importer.make_armatures(mContext, *objects_to_scale);
        armature_importer.make_shape_keys();
        DAG_relations_tag_update(bmain);
 
@@ -517,7 +517,7 @@ std::vector<Object *> *DocumentImporter::write_node(COLLADAFW::Node *node, COLLA
                        name.c_str());
 
        if (is_joint) {
-               if (parent_node == NULL) {
+               if (parent_node == NULL && !is_library_node) {
                        // A Joint on root level is a skeleton without root node.
                        // Here we add the armature "on the fly":
                        par = bc_add_object(sce, OB_ARMATURE, std::string("Armature").c_str());
index 783f58e..2c52d73 100644 (file)
@@ -33,6 +33,7 @@ struct ImportSettings {
 public:
        bool import_units;
        bool find_chains;
+       bool auto_connect;
        bool fix_orientation;
        int  min_chain_length;
        char *filepath;
index 76f2454..3addddd 100644 (file)
@@ -211,15 +211,27 @@ void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
 MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
 }
 
-void MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
+bool MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index, unsigned int *indices, int loop_count)
 {
        mpoly->loopstart = loop_index;
        mpoly->totloop   = loop_count;
-
+       bool broken_loop = false;
        for (int index=0; index < loop_count; index++) {
+
+               /* Test if loop defines a hole */
+               if (!broken_loop) {
+                       for (int i = 0; i < index; i++) {
+                               if (indices[i] == indices[index]) {
+                                       // duplicate index -> not good
+                                       broken_loop = true;
+                               }
+                       }
+               }
+
                mloop->v = indices[index];
                mloop++;
        }
+       return broken_loop;
 }
 
 void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count)
@@ -698,6 +710,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
                        COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray();
                        COLLADAFW::IndexListArray& index_list_array_vcolor  = mp->getColorIndicesArray();
 
+                       int invalid_loop_holes = 0;
                        for (unsigned int j = 0; j < prim_totpoly; j++) {
 
                                // Vertices in polygon:
@@ -705,8 +718,12 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
                                if (vcount < 0) {
                                        continue; // TODO: add support for holes
                                }
-                               set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
 
+                               bool broken_loop = set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
+                               if (broken_loop)
+                               {
+                                       invalid_loop_holes += 1;
+                               }
 
                                for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) {
                                        // get mtface by face index and uv set index
@@ -754,6 +771,11 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
 
                                position_indices += vcount;
                        }
+
+                       if (invalid_loop_holes > 0)
+                       {
+                               fprintf(stderr, "Collada import: Mesh [%s] : contains %d unsupported loops (holes).\n", me->id.name, invalid_loop_holes);
+                       }
                }
 
                else if (collada_meshtype == COLLADAFW::MeshPrimitive::LINES) {
index 9d5fefb..d6426fb 100644 (file)
@@ -109,7 +109,7 @@ private:
        std::map<COLLADAFW::UniqueId, MaterialIdPrimitiveArrayMap> geom_uid_mat_mapping_map; // crazy name!
        std::multimap<COLLADAFW::UniqueId, COLLADAFW::UniqueId> materials_mapped_to_geom; //< materials that have already been mapped to a geometry. A pair of geom uid and mat uid, one geometry can have several materials
        
-       void set_poly_indices(MPoly *mpoly,
+       bool set_poly_indices(MPoly *mpoly,
                                                  MLoop *mloop,
                                                  int loop_index,
                                                  unsigned int *indices,
index 71875d6..7242a24 100644 (file)
@@ -230,6 +230,7 @@ void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::Unique
        ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature);
        ArmatureModifierData *amd = (ArmatureModifierData *)md;
        amd->object = ob_arm;
+       struct bArmature *armature = (bArmature *)ob_arm->data;
 
 #if 1
        bc_set_parent(ob, ob_arm, C);
index e1b8a2d..fe8b1d2 100644 (file)
@@ -46,6 +46,7 @@ int collada_import(bContext *C,
                                   const char *filepath,
                                   int import_units,
                                   int find_chains,
+                                  int auto_connect,
                                   int fix_orientation,
                                   int min_chain_length)
 {
@@ -53,6 +54,7 @@ int collada_import(bContext *C,
        ImportSettings import_settings;
        import_settings.filepath         = (char *)filepath;
        import_settings.import_units     = import_units != 0;
+       import_settings.auto_connect     = auto_connect != 0;
        import_settings.find_chains      = find_chains != 0;
        import_settings.fix_orientation  = fix_orientation != 0;
        import_settings.min_chain_length = min_chain_length;
index db8ea88..0017c66 100644 (file)
@@ -57,6 +57,7 @@ int collada_import(struct bContext *C,
                    const char *filepath,
                                   int import_units,
                                   int find_chains,
+                                  int auto_connect,
                                   int fix_orientation,
                                   int min_chain_length);
 
index 74f8dca..ee371f7 100644 (file)
@@ -120,7 +120,7 @@ private:
        float roll;
 
        int   bone_layers;
-       bool  use_connect;
+       int   use_connect;
        bool  has_custom_tail;
        bool  has_custom_roll;
 
index 17b6acf..688d4ad 100644 (file)
@@ -294,16 +294,15 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
        for (Base *base = (Base *)scene->base.first; base; base = base->next) {
                Object *ob = base->object;
 
-               /* object itself */
-               build_object(scene, base, ob);
-
                /* object that this is a proxy for */
                // XXX: the way that proxies work needs to be completely reviewed!
                if (ob->proxy) {
                        ob->proxy->proxy_from = ob;
-                       build_object(scene, base, ob->proxy);
                }
 
+               /* object itself */
+               build_object(scene, base, ob);
+
                /* Object dupligroup. */
                if (ob->dup_group) {
                        build_group(scene, base, ob->dup_group);
@@ -479,6 +478,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob)
        if (ob->gpd) {
                build_gpencil(ob->gpd);
        }
+
+       if (ob->proxy != NULL) {
+               add_operation_node(&ob->id, DEPSNODE_TYPE_PROXY, DEPSOP_TYPE_POST,
+                                  function_bind(BKE_object_eval_proxy_backlink, _1, ob),
+                                  DEG_OPCODE_PLACEHOLDER, "Parameters Eval");
+       }
 }
 
 void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
index 6564292..ced53bd 100644 (file)
@@ -264,6 +264,13 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
        for (Base *base = (Base *)scene->base.first; base; base = base->next) {
                Object *ob = base->object;
 
+               /* Object that this is a proxy for.
+                * Just makes sure backlink is correct.
+                */
+               if (ob->proxy) {
+                       ob->proxy->proxy_from = ob;
+               }
+
                /* object itself */
                build_object(bmain, scene, ob);
 
@@ -431,7 +438,6 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
                                break;
                        }
 
-
                        case OB_ARMATURE: /* Pose */
                                if (ob->id.lib != NULL && ob->proxy_from != NULL) {
                                        build_proxy_rig(ob);
index af68f5c..30d2438 100644 (file)
@@ -84,6 +84,9 @@ static void flush_init_func(void *data_v, int i)
        id_node->done = 0;
        node->scheduled = false;
        node->owner->flags &= ~DEPSCOMP_FULLY_SCHEDULED;
+       if (node->owner->type == DEPSNODE_TYPE_PROXY) {
+               node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+       }
 }
 
 /* Flush updates from tagged nodes outwards until all affected nodes
index 51f962d..a82cca9 100644 (file)
@@ -753,7 +753,7 @@ EnumPropertyItem prop_driver_create_mapping_types[] = {
         "Create drivers for each pair of corresponding elements"},
         
        {CREATEDRIVER_MAPPING_NONE_ALL, "NONE_ALL", ICON_HAND, "Manually Create Later",
-        "Create drivers for all properites without assigning any targets yet"},
+        "Create drivers for all properties without assigning any targets yet"},
        {CREATEDRIVER_MAPPING_NONE,     "NONE_SINGLE", 0, "Manually Create Later (Single)",
         "Create driver for this property only and without assigning any targets yet"},
        {0, NULL, 0, NULL, NULL}
index 5530e29..cc4c180 100644 (file)
@@ -980,7 +980,11 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
        if (ts->snap_mode == SCE_SNAP_MODE_VOLUME) {
                float size;
                if (peelObjectsSnapContext(
-                       snap_context, mvalf, SNAP_ALL,
+                       snap_context, mvalf,
+                       &(const struct SnapObjectParams){
+                           .snap_select = SNAP_NOT_SELECTED,
+                           .use_object_edit_cage = false,
+                       },
                        (ts->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
                        loc, dummy_no, &size))
                {
@@ -1017,9 +1021,10 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S
                {
                        if (ED_transform_snap_object_project_view3d(
                                snap_context,
+                               ts->snap_mode,
                                &(const struct SnapObjectParams){
                                    .snap_select = SNAP_NOT_SELECTED,
-                                   .snap_to = ts->snap_mode,
+                                   .use_object_edit_cage = false,
                                },
                                mvalf, &dist_px, NULL,
                                loc, dummy_no))
index 18fdcb5..420f72f 100644 (file)
@@ -5004,9 +5004,10 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
 
                        ED_transform_snap_object_project_view3d_mixed(
                                snap_context,
+                               SCE_SELECT_FACE,
                                &(const struct SnapObjectParams){
-                                   .snap_select = SNAP_NOT_OBEDIT,
-                                   .snap_to_flag = SCE_SELECT_FACE,
+                                   .snap_select = (vc.scene->obedit != NULL) ? SNAP_NOT_ACTIVE : SNAP_ALL,
+                                   .use_object_edit_cage = false,
                                },
                                mval, NULL, true,
                                location, NULL);
index f18e778..511dae0 100644 (file)
@@ -40,12 +40,12 @@ struct Scene;
 struct Object;
 
 /* rigidbody_object.c */
-bool ED_rigidbody_object_add(struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
-void ED_rigidbody_object_remove(struct Scene *scene, struct Object *ob);
+bool ED_rigidbody_object_add(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
+void ED_rigidbody_object_remove(struct Main *bmain, struct Scene *scene, struct Object *ob);
 
 /* rigidbody_constraint.c */
-bool ED_rigidbody_constraint_add(struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
-void ED_rigidbody_constraint_remove(struct Scene *scene, struct Object *ob);
+bool ED_rigidbody_constraint_add(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports);
+void ED_rigidbody_constraint_remove(struct Main *bmain, struct Scene *scene, struct Object *ob);
 
 /* operators */
 void ED_operatortypes_physics(void);
index effecf4..1c41b14 100644 (file)
@@ -42,6 +42,7 @@ typedef struct ScreenAnimData {
        int sfra;               /* frame that playback was started from */
        int nextfra;            /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */
        double last_duration;   /* used for frame dropping */
+       bool from_anim_edit;    /* playback was invoked from animation editor */
 } ScreenAnimData;
 
 /* for animplayer */
index 933f480..ebd2a3d 100644 (file)
@@ -45,6 +45,7 @@ struct wmKeyMap;
 struct wmOperatorType;
 struct Main;
 struct SnapObjectContext;
+struct SnapObjectParams;
 
 void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid);
 void transform_operatortypes(void);
@@ -161,25 +162,27 @@ void BIF_draw_manipulator(const struct bContext *C);
 typedef enum SnapSelect {
        SNAP_ALL = 0,
        SNAP_NOT_SELECTED = 1,
-       SNAP_NOT_OBEDIT = 2
+       SNAP_NOT_ACTIVE = 2,
 } SnapSelect;
 
 #define SNAP_MIN_DISTANCE 30
 
 bool peelObjectsTransform(
-        struct TransInfo *t, const float mval[2],
-        SnapSelect snap_select, bool use_peel_object,
+        struct TransInfo *t,
+        const float mval[2],
+        const bool use_peel_object,
         /* return args */
         float r_loc[3], float r_no[3], float *r_thickness);
 bool peelObjectsSnapContext(
         struct SnapObjectContext *sctx,
         const float mval[2],
-        SnapSelect snap_select, bool use_peel_object,
+        const struct SnapObjectParams *params,
+        const bool use_peel_object,
         /* return args */
         float r_loc[3], float r_no[3], float *r_thickness);
 
 bool snapObjectsTransform(
-        struct TransInfo *t, const float mval[2], SnapSelect snap_select,
+        struct TransInfo *t, const float mval[2],
         float *dist_px,
         /* return args */
         float r_loc[3], float r_no[3]);
index 900b759..baf4ed5 100644 (file)
@@ -57,17 +57,12 @@ struct SnapObjectHitDepth {
        unsigned int ob_uuid;
 };
 
+/** parameters that define which objects will be used to snap. */
 struct SnapObjectParams {
-       int snap_select;  /* SnapSelect */
-       union {
-               unsigned int snap_to : 4;
-               /* snap_target_flag: Snap to vert/edge/face. */
-               unsigned int snap_to_flag : 4;
-       };
+       /* special context sensitive handling for the active or selected object */
+       char snap_select;
        /* use editmode cage */
-       unsigned int use_object_edit : 1;
-       /* special context sensitive handling for the active object */
-       unsigned int use_object_active : 1;
+       unsigned int use_object_edit_cage : 1;
 };
 
 enum {
@@ -93,6 +88,7 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
 
 bool ED_transform_snap_object_project_ray_ex(
         struct SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3], float *ray_depth,
         /* return args */
@@ -100,11 +96,13 @@ bool ED_transform_snap_object_project_ray_ex(
         struct Object **r_ob, float r_obmat[4][4]);
 bool ED_transform_snap_object_project_ray(
         SnapObjectContext *sctx,
+        const struct SnapObjectParams *params,
         const float ray_origin[3], const float ray_direction[3], float *ray_depth,
         float r_co[3], float r_no[3]);
 
 bool ED_transform_snap_object_project_ray_all(
         SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3],
         float ray_depth, bool sort,
@@ -112,12 +110,14 @@ bool ED_transform_snap_object_project_ray_all(
 
 bool ED_transform_snap_object_project_view3d_ex(
         struct SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float mval[2], float *dist_px,
         float *ray_depth,
         float r_loc[3], float r_no[3], int *r_index);
 bool ED_transform_snap_object_project_view3d(
         struct SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float mval[2], float *dist_px,
         float *ray_depth,
@@ -125,6 +125,7 @@ bool ED_transform_snap_object_project_view3d(
         float r_loc[3], float r_no[3]);
 bool ED_transform_snap_object_project_view3d_mixed(
         SnapObjectContext *sctx,
+        const unsigned short snap_to_flag,
         const struct SnapObjectParams *params,
         const float mval_fl[2], float *dist_px,
         bool use_depth,
index 10ab85a..5b8b8ae 100644 (file)
@@ -634,6 +634,15 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
        return ptr;
 }
 
+/**
+ * Check if a #uiAfterFunc is needed for this button.
+ */
+static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
+{
+       return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop || block->handle_func ||
+               (but->type == UI_BTYPE_BUT_MENU && block->butm_func));
+}
+
 static void ui_apply_but_func(bContext *C, uiBut *but)
 {
        uiAfterFunc *after;
@@ -643,9 +652,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
         * handling is done, i.e. menus are closed, in order to avoid conflicts
         * with these functions removing the buttons we are working with */
 
-       if (but->func || but->funcN || block->handle_func || but->rename_func ||
-           (but->type == UI_BTYPE_BUT_MENU && block->butm_func) || but->optype || but->rnaprop)
-       {
+       if (ui_afterfunc_check(block, but)) {
                after = ui_afterfunc_new();
 
                if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) {
@@ -899,7 +906,8 @@ static void ui_apply_but_TEX(bContext *C, uiBut *but, uiHandleButtonData *data)
                 * having typed something already. */
                but->rename_orig = BLI_strdup(data->origstr);
        }
-       else {
+       /* only if there are afterfuncs, otherwise 'renam_orig' isn't freed */
+       else if (ui_afterfunc_check(but->block, but)) {
                but->rename_orig = data->origstr;
                data->origstr = NULL;
        }
index 7a9c3e8..ff29a6f 100644 (file)
@@ -897,7 +897,7 @@ static int edittranslation_exec(bContext *C, wmOperator *op)
                }
                ot = WM_operatortype_find(EDTSRC_I18N_OP_NAME, 0);
                if (ot == NULL) {
-                       BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate addon "
+                       BKE_reportf(op->reports, RPT_ERROR, "Could not find operator '%s'! Please enable ui_translate add-on "
                                                            "in the User Preferences", EDTSRC_I18N_OP_NAME);
                        return OPERATOR_CANCELLED;
                }
index acb8e8e..b1ca95e 100644 (file)
@@ -379,6 +379,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
        char filename[FILE_MAX];
        int import_units;
        int find_chains;
+       int auto_connect;
        int fix_orientation;
        int  min_chain_length;
 
@@ -390,6 +391,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
        /* Options panel */
        import_units     = RNA_boolean_get(op->ptr, "import_units");
        find_chains      = RNA_boolean_get(op->ptr, "find_chains");
+       auto_connect     = RNA_boolean_get(op->ptr, "auto_connect");
        fix_orientation  = RNA_boolean_get(op->ptr, "fix_orientation");
        min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
 
@@ -398,6 +400,7 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
                C, filename,
                import_units,
                find_chains,
+                       auto_connect,
                fix_orientation,
                min_chain_length))
        {
@@ -431,6 +434,9 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
        row = uiLayoutRow(box, false);
        uiItemR(row, imfptr, "find_chains", 0, NULL, ICON_NONE);
 
+       row = uiLayoutRow(box, false);
+       uiItemR(row, imfptr, "auto_connect", 0, NULL, ICON_NONE);
+
        row = uiLayoutRow(box, false);
        uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
 }
@@ -474,6 +480,10 @@ void WM_OT_collada_import(wmOperatorType *ot)
                "find_chains", 0, "Find Bone Chains",
                "Find best matching Bone Chains and ensure bones in chain are connected");
 
+       RNA_def_boolean(ot->srna,
+               "auto_connect", 0, "Auto Connect",
+               "set use_connect for parent bones which have exactly one child bone");
+
        RNA_def_int(ot->srna,
                "min_chain_length",
                0,
index 242cbf7..0f871cd 100644 (file)
@@ -58,6 +58,9 @@
 
 #define MVAL_PIXEL_MARGIN  5.0f
 
+/* until implement profile = 0 case, need to clamp somewhat above zero */
+#define PROFILE_HARD_MIN 0.15f
+
 typedef struct {
        BMEditMesh *em;
        float initial_length;
@@ -71,13 +74,14 @@ typedef struct {
        BMBackup mesh_backup;
        void *draw_handle_pixel;
        short twtype;
+       bool mouse_controls_profile;
        float segments;     /* Segments as float so smooth mouse pan works in small increments */
 } BevelData;
 
 static void edbm_bevel_update_header(bContext *C, wmOperator *op)
 {
        const char *str = IFACE_("Confirm: (Enter/LMB), Cancel: (Esc/RMB), Mode: %s (M), Clamp Overlap: %s (C), "
-                                "Vertex Only: %s (V), Offset: %s, Segments: %d");
+                                "Vertex Only: %s (V), Profile Control: %s (P), Offset: %s, Segments: %d");
 
        char msg[UI_MAX_DRAW_STR];
        ScrArea *sa = CTX_wm_area(C);
@@ -101,6 +105,7 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
                BLI_snprintf(msg, sizeof(msg), str, type_str,
                             WM_bool_as_string(RNA_boolean_get(op->ptr, "clamp_overlap")),
                             WM_bool_as_string(RNA_boolean_get(op->ptr, "vertex_only")),
+                            WM_bool_as_string(opdata->mouse_controls_profile),
                             offset_str, RNA_int_get(op->ptr, "segments"));
 
                ED_area_headerprint(sa, msg);
@@ -123,6 +128,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
        opdata->em = em;
        opdata->is_modal = is_modal;
        opdata->shift_factor = -1.0f;
+       opdata->mouse_controls_profile = false;
 
        initNumInput(&opdata->num_input);
        opdata->num_input.idx_max = 0;
@@ -291,7 +297,7 @@ static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
 {
        BevelData *opdata = op->customdata;
        bool use_dist;
-       bool is_percent;
+       bool is_percent, is_profile;
        float mdiff[2];
        float factor;
 
@@ -299,15 +305,20 @@ static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
        mdiff[1] = opdata->mcenter[1] - event->mval[1];
        is_percent = (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT);
        use_dist = !is_percent;
+       is_profile = opdata->mouse_controls_profile;
 
        factor = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length) * opdata->pixel_size;
 
        /* Fake shift-transform... */
        if (event->shift) {
                if (opdata->shift_factor < 0.0f) {
-                       opdata->shift_factor = RNA_float_get(op->ptr, "offset");
-                       if (is_percent) {
-                               opdata->shift_factor /= 100.0f;
+                       if (is_profile)
+                               opdata->shift_factor = RNA_float_get(op->ptr, "profile");
+                       else {
+                               opdata->shift_factor = RNA_float_get(op->ptr, "offset");
+                               if (is_percent) {
+                                       opdata->shift_factor /= 100.0f;
+                               }
                        }
                }
                factor = (factor - opdata->shift_factor) * 0.1f + opdata->shift_factor;
@@ -316,14 +327,19 @@ static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event)
                opdata->shift_factor = -1.0f;
        }
 
-       /* clamp differently based on distance/factor */
-       if (use_dist) {
-               if (factor < 0.0f) factor = 0.0f;
+       /* clamp differently based on distance/factor/profile */
+       if (is_profile) {
+               CLAMP(factor, PROFILE_HARD_MIN, 1.0f);
        }
        else {
-               CLAMP(factor, 0.0f, 1.0f);
-               if (is_percent) {
-                       factor *= 100.0f;
+               if (use_dist) {
+                       if (factor < 0.0f) factor = 0.0f;
+               }
+               else {
+                       CLAMP(factor, 0.0f, 1.0f);
+                       if (is_percent) {
+                               factor *= 100.0f;
+                       }
                }
        }
 
@@ -355,7 +371,10 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
                        case MOUSEMOVE:
                                if (!has_numinput) {
                                        const float factor = edbm_bevel_mval_factor(op, event);
-                                       RNA_float_set(op->ptr, "offset", factor);
+                                       if (opdata->mouse_controls_profile)
+                                               RNA_float_set(op->ptr, "profile", factor);
+                                       else
+                                               RNA_float_set(op->ptr, "offset", factor);
 
                                        edbm_bevel_calc(op);
                                        edbm_bevel_update_header(C, op);
@@ -448,6 +467,11 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event)
                                edbm_bevel_update_header(C, op);
                                handled = true;
                                break;
+                       case PKEY:
+                               if (event->val == KM_RELEASE)
+                                       break;
+                               opdata->mouse_controls_profile = !opdata->mouse_controls_profile;
+                               break;
                        case VKEY:
                                if (event->val == KM_RELEASE)
                                        break;
@@ -519,7 +543,8 @@ void MESH_OT_bevel(wmOperatorType *ot)
        prop = RNA_def_float(ot->srna, "offset", 0.0f, -1e6f, 1e6f, "Amount", "", 0.0f, 1.0f);
        RNA_def_property_float_array_funcs_runtime(prop, NULL, NULL, mesh_ot_bevel_offset_range_func);
        RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8);
-       RNA_def_float(ot->srna, "profile", 0.5f, 0.15f, 1.0f, "Profile", "Controls profile shape (0.5 = round)", 0.15f, 1.0f);
+       RNA_def_float(ot->srna, "profile", 0.5f, PROFILE_HARD_MIN, 1.0f, "Profile",
+                       "Controls profile shape (0.5 = round)", PROFILE_HARD_MIN, 1.0f);
        RNA_def_boolean(ot->srna, "vertex_only", false, "Vertex Only", "Bevel only vertices");
        RNA_def_boolean(ot->srna, "clamp_overlap", false, "Clamp Overlap",
                        "Do not allow beveled edges/vertices to overlap each other");
index ba17684..efe1797 100644 (file)
@@ -312,9 +312,10 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em)
                        if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
                                if (ED_transform_snap_object_project_view3d_mixed(
                                        snap_context,
+                                       SCE_SELECT_FACE,
                                        &(const struct SnapObjectParams){
-                                           .snap_select = SNAP_NOT_OBEDIT,
-                                           .snap_to_flag = SCE_SELECT_FACE,
+                                           .snap_select = SNAP_NOT_ACTIVE,
+                                           .use_object_edit_cage = false,
                                        },
                                        mval, NULL, true,
                                        co_proj, NULL))
index 7e85ab1..0ceb177 100644 (file)
@@ -1600,7 +1600,7 @@ static int convert_exec(bContext *C, wmOperator *op)
 
                        if (newob->type == OB_CURVE) {
                                BKE_object_free_modifiers(newob);   /* after derivedmesh calls! */
-                               ED_rigidbody_object_remove(scene, newob);
+                               ED_rigidbody_object_remove(bmain, scene, newob);
                        }
                }
                else if (ob->type == OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
index f955995..1bfc162 100644 (file)
@@ -41,6 +41,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_group.h"
+#include "BKE_main.h"
 #include "BKE_report.h"
 #include "BKE_rigidbody.h"
 
@@ -70,7 +71,7 @@ static int ED_operator_rigidbody_con_active_poll(bContext *C)
 }
 
 
-bool ED_rigidbody_constraint_add(Scene *scene, Object *ob, int type, ReportList *reports)
+bool ED_rigidbody_constraint_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
 {
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
 
@@ -81,7 +82,7 @@ bool ED_rigidbody_constraint_add(Scene *scene, Object *ob, int type, ReportList
        }
        /* create constraint group if it doesn't already exits */
        if (rbw->constraints == NULL) {
-               rbw->constraints = BKE_group_add(G.main, "RigidBodyConstraints");
+               rbw->constraints = BKE_group_add(bmain, "RigidBodyConstraints");
        }
        /* make rigidbody constraint settings */
        ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
@@ -90,11 +91,12 @@ bool ED_rigidbody_constraint_add(Scene *scene, Object *ob, int type, ReportList
        /* add constraint to rigid body constraint group */
        BKE_group_object_add(rbw->constraints, ob, scene, NULL);
 
+       DAG_relations_tag_update(bmain);
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
        return true;
 }
 
-void ED_rigidbody_constraint_remove(Scene *scene, Object *ob)
+void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
 {
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
 
@@ -102,6 +104,7 @@ void ED_rigidbody_constraint_remove(Scene *scene, Object *ob)
        if (rbw)
                BKE_group_object_unlink(rbw->constraints, ob, scene, NULL);
 
+       DAG_relations_tag_update(bmain);
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 }
 
@@ -112,6 +115,7 @@ void ED_rigidbody_constraint_remove(Scene *scene, Object *ob)
 
 static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
        Object *ob = (scene) ? OBACT : NULL;
@@ -124,7 +128,7 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
        /* apply to active object */
-       changed = ED_rigidbody_constraint_add(scene, ob, type, op->reports);
+       changed = ED_rigidbody_constraint_add(bmain, scene, ob, type, op->reports);
 
        if (changed) {
                /* send updates */
@@ -160,6 +164,7 @@ void RIGIDBODY_OT_constraint_add(wmOperatorType *ot)
 
 static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = (scene) ? OBACT : NULL;
 
@@ -173,7 +178,7 @@ static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
        else {
-               ED_rigidbody_constraint_remove(scene, ob);
+               ED_rigidbody_constraint_remove(bmain, scene, ob);
        }
 
        /* send updates */
index 26d8af8..30597d9 100644 (file)
@@ -46,6 +46,7 @@
 #include "BKE_depsgraph.h"
 #include "BKE_global.h"
 #include "BKE_group.h"
+#include "BKE_main.h"
 #include "BKE_report.h"
 #include "BKE_rigidbody.h"
 
@@ -87,7 +88,7 @@ static int ED_operator_rigidbody_add_poll(bContext *C)
 
 /* ----------------- */
 
-bool ED_rigidbody_object_add(Scene *scene, Object *ob, int type, ReportList *reports)
+bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
 {
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
 
@@ -107,7 +108,7 @@ bool ED_rigidbody_object_add(Scene *scene, Object *ob, int type, ReportList *rep
                scene->rigidbody_world = rbw;
        }
        if (rbw->group == NULL) {
-               rbw->group = BKE_group_add(G.main, "RigidBodyWorld");
+               rbw->group = BKE_group_add(bmain, "RigidBodyWorld");
        }
 
        /* make rigidbody object settings */
@@ -120,12 +121,13 @@ bool ED_rigidbody_object_add(Scene *scene, Object *ob, int type, ReportList *rep
        /* add object to rigid body group */
        BKE_group_object_add(rbw->group, ob, scene, NULL);
 
+       DAG_relations_tag_update(bmain);
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 
        return true;
 }
 
-void ED_rigidbody_object_remove(Scene *scene, Object *ob)
+void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
 {
        RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
 
@@ -133,6 +135,7 @@ void ED_rigidbody_object_remove(Scene *scene, Object *ob)
        if (rbw)
                BKE_group_object_unlink(rbw->group, ob, scene, NULL);
 
+       DAG_relations_tag_update(bmain);
        DAG_id_tag_update(&ob->id, OB_RECALC_OB);
 }
 
@@ -143,13 +146,14 @@ void ED_rigidbody_object_remove(Scene *scene, Object *ob)
 
 static int rigidbody_object_add_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = ED_object_active_context(C);
        int type = RNA_enum_get(op->ptr, "type");
        bool changed;
 
        /* apply to active object */
-       changed = ED_rigidbody_object_add(scene, ob, type, op->reports);
+       changed = ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
 
        if (changed) {
                /* send updates */
@@ -186,13 +190,14 @@ void RIGIDBODY_OT_object_add(wmOperatorType *ot)
 
 static int rigidbody_object_remove_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = ED_object_active_context(C);
        bool changed = false;
 
        /* apply to active object */
        if (!ELEM(NULL, ob, ob->rigidbody_object)) {
-               ED_rigidbody_object_remove(scene, ob);
+               ED_rigidbody_object_remove(bmain, scene, ob);
                changed = true;
        }
 
@@ -232,13 +237,14 @@ void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
 
 static int rigidbody_objects_add_exec(bContext *C, wmOperator *op)
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        int type = RNA_enum_get(op->ptr, "type");
        bool changed = false;
 
        /* create rigid body objects and add them to the world's group */
        CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
-               changed |= ED_rigidbody_object_add(scene, ob, type, op->reports);
+               changed |= ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
        }
        CTX_DATA_END;
 
@@ -277,6 +283,7 @@ void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
 
 static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
        bool changed = false;
 
@@ -284,7 +291,7 @@ static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
        CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
        {
                if (ob->rigidbody_object) {
-                       ED_rigidbody_object_remove(scene, ob);
+                       ED_rigidbody_object_remove(bmain, scene, ob);
                        changed = true;
                }
        }
index 23c6aa3..a459f98 100644 (file)
@@ -2070,7 +2070,10 @@ void ED_screen_animation_timer(bContext *C, int redraws, int refresh, int sync,
                sad->refresh = refresh;
                sad->flag |= (enable < 0) ? ANIMPLAY_FLAG_REVERSE : 0;
                sad->flag |= (sync == 0) ? ANIMPLAY_FLAG_NO_SYNC : (sync == 1) ? ANIMPLAY_FLAG_SYNC : 0;
-               
+
+               ScrArea *sa = CTX_wm_area(C);
+               sad->from_anim_edit = (ELEM(sa->spacetype, SPACE_IPO, SPACE_ACTION, SPACE_NLA, SPACE_TIME));
+
                screen->animtimer->customdata = sad;
                
        }
index 4111f67..f340f71 100644 (file)
@@ -3355,24 +3355,24 @@ static int match_area_with_refresh(int spacetype, int refresh)
        return 0;
 }
 
-static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
+static int match_region_with_redraws(int spacetype, int regiontype, int redraws, bool from_anim_edit)
 {
        if (regiontype == RGN_TYPE_WINDOW) {
                
                switch (spacetype) {
                        case SPACE_VIEW3D:
-                               if (redraws & TIME_ALL_3D_WIN)
+                               if ((redraws & TIME_ALL_3D_WIN) || from_anim_edit)
                                        return 1;
                                break;
                        case SPACE_IPO:
                        case SPACE_ACTION:
                        case SPACE_NLA:
-                               if (redraws & TIME_ALL_ANIM_WIN)
+                               if ((redraws & TIME_ALL_ANIM_WIN) || from_anim_edit)
                                        return 1;
                                break;
                        case SPACE_TIME:
                                /* if only 1 window or 3d windows, we do timeline too */
-                               if (redraws & (TIME_ALL_ANIM_WIN | TIME_REGION | TIME_ALL_3D_WIN))
+                               if ((redraws & (TIME_ALL_ANIM_WIN | TIME_REGION | TIME_ALL_3D_WIN)) || from_anim_edit)
                                        return 1;
                                break;
                        case SPACE_BUTS:
@@ -3380,7 +3380,7 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
                                        return 1;
                                break;
                        case SPACE_SEQ:
-                               if (redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN))
+                               if ((redraws & (TIME_SEQ | TIME_ALL_ANIM_WIN)) || from_anim_edit)
                                        return 1;
                                break;
                        case SPACE_NODE:
@@ -3388,11 +3388,11 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws)
                                        return 1;
                                break;
                        case SPACE_IMAGE:
-                               if (redraws & TIME_ALL_IMAGE_WIN)
+                               if ((redraws & TIME_ALL_IMAGE_WIN) || from_anim_edit)
                                        return 1;
                                break;
                        case SPACE_CLIP:
-                               if (redraws & TIME_CLIPS)
+                               if ((redraws & TIME_CLIPS) || from_anim_edit)
                                        return 1;
                                break;
                                
@@ -3572,7 +3572,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv
                                        if (ar == sad->ar) {
                                                redraw = true;
                                        }
-                                       else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws)) {
+                                       else if (match_region_with_redraws(sa->spacetype, ar->regiontype, sad->redraws, sad->from_anim_edit)) {
                                                redraw = true;
                                        }
 
index e4e9976..eba9448 100644 (file)
@@ -1016,7 +1016,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
        translation[1] = y;
        outline_alpha = 0.5;
        outline_col = brush->add_col;
-       final_radius = BKE_brush_size_get(scene, brush) * zoomx;
+       final_radius = (BKE_brush_size_get(scene, brush) * zoomx) / U.pixelsize;
 
        /* don't calculate rake angles while a stroke is active because the rake variables are global and
         * we may get interference with the stroke itself. For line strokes, such interference is visible */
index c0947da..8261a21 100644 (file)
@@ -707,10 +707,13 @@ static void insert_action_keys(bAnimContext *ac, short mode)
                 *                       so it's easier for now to just read the F-Curve directly.
                 *                       (TODO: add the full-blown PointerRNA relative parsing case here...)
                 */
-               if (ale->id && !ale->owner)
+               if (ale->id && !ale->owner) {
                        insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
-               else
-                       insert_vert_fcurve(fcu, cfra, fcu->curval, ts->keyframe_type, 0);
+               }
+               else {
+                       const float curval = evaluate_fcurve(fcu, cfra);
+                       insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+               }
                
                ale->update |= ANIM_UPDATE_DEFAULT;
        }
index f106399..f38d368 100644 (file)
@@ -606,10 +606,13 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
                         * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end
                         *                        up adding the keyframes on a new F-Curve in the action data instead.
                         */
-                       if (ale->id && !ale->owner && !fcu->driver)
+                       if (ale->id && !ale->owner && !fcu->driver) {
                                insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
-                       else
-                               insert_vert_fcurve(fcu, cfra, fcu->curval, ts->keyframe_type, 0);
+                       }
+                       else {
+                               const float curval = evaluate_fcurve(fcu, cfra);
+                               insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
+                       }
                        
                        ale->update |= ANIM_UPDATE_DEFAULT;
                }
index d060a4a..0e012b4 100644 (file)
@@ -1178,10 +1178,10 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
        if (scene->r.mode & R_BORDER) {
                float x3, y3, x4, y4;
 
-               x3 = x1i + 1 + roundf(scene->r.border.xmin * (x2 - x1));
-               y3 = y1i + 1 + roundf(scene->r.border.ymin * (y2 - y1));
-               x4 = x1i + 1 + roundf(scene->r.border.xmax * (x2 - x1));
-               y4 = y1i + 1 + roundf(scene->r.border.ymax * (y2 - y1));
+               x3 = floorf(x1 + (scene->r.border.xmin * (x2 - x1))) - 1;
+               y3 = floorf(y1 + (scene->r.border.ymin * (y2 - y1))) - 1;
+               x4 = floorf(x1 + (scene->r.border.xmax * (x2 - x1))) + (U.pixelsize - 1);
+               y4 = floorf(y1 + (scene->r.border.ymax * (y2 - y1))) + (U.pixelsize - 1);
 
                cpack(0x4040FF);
                sdrawbox(x3,  y3,  x4,  y4);
index dfa7675..c6951c7 100644 (file)
@@ -679,9 +679,10 @@ static bool view3d_ruler_item_mousemove(
 
                        if (ED_transform_snap_object_project_view3d_mixed(
                                ruler_info->snap_context,
+                               SCE_SELECT_FACE,
                                &(const struct SnapObjectParams){
                                    .snap_select = SNAP_ALL,
-                                   .snap_to_flag = SCE_SELECT_FACE,
+                                   .use_object_edit_cage = true,
                                },
                                mval_fl, &dist_px, true,
                                co, ray_normal))
@@ -691,6 +692,10 @@ static bool view3d_ruler_item_mousemove(
                                madd_v3_v3v3fl(ray_start, co, ray_normal, eps_bias);
                                ED_transform_snap_object_project_ray(
                                        ruler_info->snap_context,
+                                       &(const struct SnapObjectParams){
+                                           .snap_select = SNAP_ALL,
+                                           .use_object_edit_cage = true,
+                                       },
                                        ray_start, ray_normal, NULL,
                                        co_other, NULL);
                        }
@@ -703,9 +708,10 @@ static bool view3d_ruler_item_mousemove(
 
                        if (ED_transform_snap_object_project_view3d_mixed(
                                ruler_info->snap_context,
+                               (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
                                &(const struct SnapObjectParams){
                                    .snap_select = SNAP_ALL,
-                                   .snap_to_flag = (SCE_SELECT_VERTEX | SCE_SELECT_EDGE) | (use_depth ? SCE_SELECT_FACE : 0),
+                                   .use_object_edit_cage = true,
                                },
                                mval_fl, &dist_px, use_depth,
                                co, NULL))
index 47f8167..384da27 100644 (file)
@@ -49,6 +49,7 @@
 
 #include "ED_screen.h"
 #include "ED_space_api.h"
+#include "ED_transform.h"
 #include "ED_transform_snap_object_context.h"
 
 #include "PIL_time.h" /* smoothview */
@@ -424,6 +425,9 @@ static bool walk_floor_distance_get(
 
        ret = ED_transform_snap_object_project_ray(
                walk->snap_context,
+               &(const struct SnapObjectParams){
+                   .snap_select = SNAP_ALL,
+               },
                ray_start, ray_normal, r_distance,
                r_location, r_normal_dummy);
 
@@ -455,6 +459,9 @@ static bool walk_ray_cast(
 
        ret = ED_transform_snap_object_project_ray(
                walk->snap_context,
+               &(const struct SnapObjectParams){
+                   .snap_select = SNAP_ALL,
+               },
                ray_start, ray_normal, NULL,
                r_location, r_normal);
 
index cb981bc..2fc116b 100644 (file)
@@ -324,7 +324,7 @@ void applyProject(TransInfo *t)
                        
                        if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
                                if (snapObjectsTransform(
-                                       t, mval_fl, t->tsnap.modeSelect, &dist_px,
+                                       t, mval_fl, &dist_px,
                                        loc, no))
                                {
 //                                     if (t->flag & (T_EDIT|T_POSE)) {
@@ -551,10 +551,10 @@ static void initSnappingMode(TransInfo *t)
                {
                        /* Exclude editmesh if using proportional edit */
                        if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
-                               t->tsnap.modeSelect = SNAP_NOT_OBEDIT;
+                               t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
                        }
                        else {
-                               t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_OBEDIT;
+                               t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_ACTIVE;
                        }
                }
                /* Object mode */
@@ -956,14 +956,14 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
                
                if (t->tsnap.mode == SCE_SNAP_MODE_VOLUME) {
                        found = peelObjectsTransform(
-                               t, mval, t->tsnap.modeSelect,
+                               t, mval,
                                (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0,
                                loc, no, NULL);
                }
                else {
                        zero_v3(no);  /* objects won't set this */
                        found = snapObjectsTransform(
-                               t, mval, t->tsnap.modeSelect, &dist_px,
+                               t, mval, &dist_px,
                                loc, no);
                }
                
@@ -1199,17 +1199,16 @@ static void TargetSnapClosest(TransInfo *t)
 }
 
 bool snapObjectsTransform(
-        TransInfo *t, const float mval[2], SnapSelect snap_select,
+        TransInfo *t, const float mval[2],
         float *dist_px,
         float r_loc[3], float r_no[3])
 {
        return ED_transform_snap_object_project_view3d_ex(
                t->tsnap.object_context,
+               t->scene->toolsettings->snap_mode,
                &(const struct SnapObjectParams){
-                   .snap_select = snap_select,
-                   .snap_to = t->scene->toolsettings->snap_mode,
-                   .use_object_edit = (t->flag & T_EDIT) != 0,
-                   .use_object_active = (t->options & CTX_GPENCIL_STROKES) == 0,
+                   .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+                   .use_object_edit_cage = (t->flag & T_EDIT) != 0,
                },
                mval, dist_px, NULL,
                r_loc, r_no, NULL);
@@ -1220,18 +1219,16 @@ bool snapObjectsTransform(
 
 bool peelObjectsSnapContext(
         SnapObjectContext *sctx,
-        const float mval[2], SnapSelect snap_select, bool use_peel_object,
+        const float mval[2],
+        const struct SnapObjectParams *params,
+        const bool use_peel_object,
         /* return args */
         float r_loc[3], float r_no[3], float *r_thickness)
 {
        ListBase depths_peel = {0};
        ED_transform_snap_object_project_all_view3d_ex(
                sctx,
-               &(const struct SnapObjectParams){
-                   .snap_to = SCE_SNAP_MODE_FACE,
-                   .snap_select = snap_select,
-                   .use_object_edit = true,
-               },
+               params,
                mval, -1.0f, false,
                &depths_peel);
 
@@ -1291,13 +1288,19 @@ bool peelObjectsSnapContext(
 
 bool peelObjectsTransform(
         TransInfo *t,
-        const float mval[2], SnapSelect snap_select, bool use_peel_object,
+        const float mval[2],
+        const bool use_peel_object,
         /* return args */
         float r_loc[3], float r_no[3], float *r_thickness)
 {
        return peelObjectsSnapContext(
                t->tsnap.object_context,
-               mval, snap_select, use_peel_object,
+               mval,
+               &(const struct SnapObjectParams){
+                   .snap_select = ((t->options & CTX_GPENCIL_STROKES) != 0) ? SNAP_NOT_ACTIVE : t->tsnap.modeSelect,
+                   .use_object_edit_cage = (t->flag & T_EDIT) != 0,
+               },
+               use_peel_object,
                r_loc, r_no, r_thickness);
 }
 
index bf4a311..b11a2d5 100644 (file)
@@ -992,7 +992,7 @@ static bool snapEditMesh(
                float imat[4][4];
                float timat[3][3]; /* transpose inverse matrix for normals */
                float ray_start_local[3], ray_normal_local[3];
-               float local_scale, local_depth, len_diff;
+               float local_scale, local_depth;
 
                invert_m4_m4(imat, obmat);
                transpose_m3_m4(timat, imat);
@@ -1089,6 +1089,7 @@ static bool snapEditMesh(
                 * been *inside* boundbox, leading to snap failures (see T38409).
                 * Note also ar might be null (see T38435), in this case we assume ray_start is ok!
                 */
+               float len_diff = 0.0f;
                if (do_ray_start_correction) {
                        /* We *need* a reasonably valid len_diff in this case.
                         * Use BHVTree to find the closest face from ray_start_local.
@@ -1098,27 +1099,24 @@ static bool snapEditMesh(
                                nearest.index = -1;
                                nearest.dist_sq = FLT_MAX;
                                /* Compute and store result. */
-                               BLI_bvhtree_find_nearest(
-                                       treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata);
-                               if (nearest.index != -1) {
+                               if (BLI_bvhtree_find_nearest(
+                                       treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata) != -1)
+                               {
                                        len_diff = sqrtf(nearest.dist_sq);
+                                       float ray_org_local[3];
+
+                                       copy_v3_v3(ray_org_local, ray_origin);
+                                       mul_m4_v3(imat, ray_org_local);
+
+                                       /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
+                                       * away ray_start values (as returned in case of ortho view3d), see T38358.
+                                       */
+                                       len_diff -= local_scale;  /* make temp start point a bit away from bbox hit point. */
+                                       madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
+                                                      len_diff - len_v3v3(ray_start_local, ray_org_local));
+                                       local_depth -= len_diff;
                                }
                        }
-                       float ray_org_local[3];
-
-                       copy_v3_v3(ray_org_local, ray_origin);
-                       mul_m4_v3(imat, ray_org_local);
-
-                       /* We pass a temp ray_start, set from object's boundbox, to avoid precision issues with very far
-                        * away ray_start values (as returned in case of ortho view3d), see T38358.
-                        */
-                       len_diff -= local_scale;  /* make temp start point a bit away from bbox hit point. */
-                       madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local,
-                                      len_diff - len_v3v3(ray_start_local, ray_org_local));
-                       local_depth -= len_diff;
-               }
-               else {
-                       len_diff = 0.0f;
                }
 
                switch (snap_to) {
@@ -1316,41 +1314,39 @@ static bool snapObject(
 
 static bool snapObjectsRay(
         SnapObjectContext *sctx,
-        SnapSelect snap_select, const short snap_to,
+        const unsigned short snap_to, const SnapSelect snap_select,
+        const bool use_object_edit_cage,
         const float mval[2], float *dist_px,
-        /* special handling of active and edit objects */
-        Base *base_act, Object *obedit,
         const float ray_start[3], const float ray_normal[3], const float ray_origin[3], float *ray_depth,
         /* return args */
         float r_loc[3], float r_no[3], int *r_index,
         Object **r_ob, float r_obmat[4][4],
         ListBase *r_hit_list)
 {
-       Base *base;
        bool retval = false;
-       bool snap_obedit_first = snap_select == SNAP_ALL && obedit;
        unsigned int ob_index = 0;
+       Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL;
+       Base *base_act = sctx->scene->basact;
 
-       if (snap_obedit_first) {
-               Object *ob = obedit;
-
-               retval |= snapObject(
-                       sctx, ob, ob->obmat, true, snap_to,
-                       mval, dist_px, ob_index++,
-                       ray_start, ray_normal, ray_origin, ray_depth,
-                       r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list);
+       bool ignore_object_selected = false, ignore_object_active = false;
+       switch (snap_select) {
+               case SNAP_ALL:
+                       break;
+               case SNAP_NOT_SELECTED:
+                       ignore_object_selected = true;
+                       break;
+               case SNAP_NOT_ACTIVE:
+                       ignore_object_active = true;
+                       break;
        }
-
-       for (base = sctx->scene->base.first; base != NULL; base = base->next) {
+       for (Base *base = sctx->scene->base.first; base != NULL; base = base->next) {
                if ((BASE_VISIBLE_BGMODE(sctx->v3d_data.v3d, sctx->scene, base)) &&
                    (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 &&
 
-                   ((snap_select == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) ||
-                    (ELEM(snap_select, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act)))
+                   !((ignore_object_selected && (base->flag & (SELECT | BA_WAS_SEL))) ||
+                     (ignore_object_active && base == base_act)))
                {
                        Object *ob = base->object;
-                       Object *ob_snap = ob;
-                       bool use_obedit = false;
 
                        if (ob->transflag & OB_DUPLI) {
                                DupliObject *dupli_ob;
@@ -1370,19 +1366,8 @@ static bool snapObjectsRay(
                                free_object_duplilist(lb);
                        }
 
-                       if (obedit) {
-                               if ((ob == obedit) &&
-                                  (snap_obedit_first || (snap_select == SNAP_NOT_OBEDIT)))
-                               {
-                                       continue;
-                               }
-
-                               if (ob->data == obedit->data) {
-                                       /* for linked objects, use the same object but a different matrix */
-                                       use_obedit = true;
-                                       ob_snap = obedit;
-                               }
-                       }
+                       bool use_obedit = (obedit != NULL) && (ob->data == obedit->data);
+                       Object *ob_snap = use_obedit ? obedit : ob;
 
                        retval |= snapObject(
                                sctx, ob_snap, ob->obmat, use_obedit, snap_to,
@@ -1487,22 +1472,18 @@ void ED_transform_snap_object_context_set_editmesh_callbacks(
 
 bool ED_transform_snap_object_project_ray_ex(
         SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3], float *ray_depth,
         float r_loc[3], float r_no[3], int *r_index,
         Object **r_ob, float r_obmat[4][4])
 {
-       Base *base_act = params->use_object_active ? sctx->scene->basact : NULL;
-       Object *obedit = params->use_object_edit ? sctx->scene->obedit : NULL;
-
        return snapObjectsRay(
                sctx,
-               params->snap_select, params->snap_to,
+               snap_to, params->snap_select, params->use_object_edit_cage,
                NULL, NULL,
-               base_act, obedit,
                ray_start, ray_normal, ray_start, ray_depth,
-               r_loc, r_no, r_index,
-               r_ob, r_obmat, NULL);
+               r_loc, r_no, r_index, r_ob, r_obmat, NULL);
 }
 
 /**
@@ -1514,14 +1495,12 @@ bool ED_transform_snap_object_project_ray_ex(
  */
 bool ED_transform_snap_object_project_ray_all(
         SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3],
         float ray_depth, bool sort,
         ListBase *r_hit_list)
 {
-       Base *base_act = params->use_object_active ? sctx->scene->basact : NULL;
-       Object *obedit = params->use_object_edit ? sctx->scene->obedit : NULL;
-
        if (ray_depth == -1.0f) {
                ray_depth = BVH_RAYCAST_DIST_MAX;
        }
@@ -1532,9 +1511,8 @@ bool ED_transform_snap_object_project_ray_all(
 
        bool retval = snapObjectsRay(
                sctx,
-               params->snap_select, params->snap_to,
+               snap_to, params->snap_select, params->use_object_edit_cage,
                NULL, NULL,
-               base_act, obedit,
                ray_start, ray_normal, ray_start, &ray_depth,
                NULL, NULL, NULL, NULL, NULL,
                r_hit_list);
@@ -1560,6 +1538,7 @@ bool ED_transform_snap_object_project_ray_all(
  */
 static bool transform_snap_context_project_ray_impl(
         SnapObjectContext *sctx,
+        const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3], float *ray_depth,
         float r_co[3], float r_no[3])
 {
@@ -1568,11 +1547,8 @@ static bool transform_snap_context_project_ray_impl(
        /* try snap edge, then face if it fails */
        ret = ED_transform_snap_object_project_ray_ex(
                sctx,
-               &(const struct SnapObjectParams){
-                   .snap_select = SNAP_ALL,
-                   .snap_to = SCE_SNAP_MODE_FACE,
-                   .use_object_edit = (sctx->scene->obedit != NULL),
-               },
+               SCE_SNAP_MODE_FACE,
+               params,
                ray_start, ray_normal, ray_depth,
                r_co, r_no, NULL,
                NULL, NULL);
@@ -1582,6 +1558,7 @@ static bool transform_snap_context_project_ray_impl(
 
 bool ED_transform_snap_object_project_ray(
         SnapObjectContext *sctx,
+        const struct SnapObjectParams *params,
         const float ray_origin[3], const float ray_direction[3], float *ray_depth,
         float r_co[3], float r_no[3])
 {
@@ -1598,12 +1575,14 @@ bool ED_transform_snap_object_project_ray(
 
        return transform_snap_context_project_ray_impl(
                sctx,
+               params,
                ray_origin, ray_direction, ray_depth,
                r_co, r_no);
 }
 
 static bool transform_snap_context_project_view3d_mixed_impl(
         SnapObjectContext *sctx,
+        const unsigned short snap_to_flag,
         const struct SnapObjectParams *params,
         const float mval[2], float *dist_px,
         bool use_depth,
@@ -1619,22 +1598,18 @@ static bool transform_snap_context_project_view3d_mixed_impl(
 
        const int  elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
 
-       BLI_assert(params->snap_to_flag != 0);
-       BLI_assert((params->snap_to_flag & ~(1 | 2 | 4)) == 0);
-
-       struct SnapObjectParams params_temp = *params;
+       BLI_assert(snap_to_flag != 0);
+       BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
 
        for (int i = 0; i < 3; i++) {
-               if ((params->snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
+               if ((snap_to_flag & (1 << i)) && (is_hit == false || use_depth)) {
                        if (use_depth == false) {
                                ray_depth = BVH_RAYCAST_DIST_MAX;
                        }
 
-                       params_temp.snap_to = elem_type[i];
-
                        if (ED_transform_snap_object_project_view3d(
                                sctx,
-                               &params_temp,
+                               elem_type[i], params,
                                mval, dist_px, &ray_depth,
                                r_co, r_no))
                        {
@@ -1661,6 +1636,7 @@ static bool transform_snap_context_project_view3d_mixed_impl(
  */
 bool ED_transform_snap_object_project_view3d_mixed(
         SnapObjectContext *sctx,
+        const unsigned short snap_to_flag,
         const struct SnapObjectParams *params,
         const float mval_fl[2], float *dist_px,
         bool use_depth,
@@ -1668,13 +1644,14 @@ bool ED_transform_snap_object_project_view3d_mixed(
 {
        return transform_snap_context_project_view3d_mixed_impl(
                sctx,
-               params,
+               snap_to_flag, params,
                mval_fl, dist_px, use_depth,
                r_co, r_no);
 }
 
 bool ED_transform_snap_object_project_view3d_ex(
         SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float mval[2], float *dist_px,
         float *ray_depth,
@@ -1695,19 +1672,17 @@ bool ED_transform_snap_object_project_view3d_ex(
                return false;
        }
 
-       Base *base_act = params->use_object_active ? sctx->scene->basact : NULL;
-       Object *obedit = params->use_object_edit ? sctx->scene->obedit : NULL;
        return snapObjectsRay(
                sctx,
-               params->snap_select, params->snap_to,
+               snap_to, params->snap_select, params->use_object_edit_cage,
                mval, dist_px,
-               base_act, obedit,
                ray_start, ray_normal, ray_orgigin, ray_depth,
                r_loc, r_no, r_index, NULL, NULL, NULL);
 }
 
 bool ED_transform_snap_object_project_view3d(
         SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float mval[2], float *dist_px,
         float *ray_depth,
@@ -1715,6 +1690,7 @@ bool ED_transform_snap_object_project_view3d(
 {
        return ED_transform_snap_object_project_view3d_ex(
                sctx,
+               snap_to,
                params,
                mval, dist_px,
                ray_depth,
@@ -1733,8 +1709,6 @@ bool ED_transform_snap_object_project_all_view3d_ex(
 {
        float ray_start[3], ray_normal[3];
 
-       BLI_assert(params->snap_to == SCE_SNAP_MODE_FACE);
-
        if (!ED_view3d_win_to_ray_ex(
                sctx->v3d_data.ar, sctx->v3d_data.v3d,
                mval, NULL, ray_normal, ray_start, true))
@@ -1744,6 +1718,7 @@ bool ED_transform_snap_object_project_all_view3d_ex(
 
        return ED_transform_snap_object_project_ray_all(
                sctx,
+               SCE_SNAP_MODE_FACE,
                params,
                ray_start, ray_normal, ray_depth, sort,
                r_hit_list);
index ee7abe0..aefaf1a 100644 (file)
@@ -49,6 +49,7 @@ struct DerivedMesh;
 struct GSet;
 struct GPUVertPointLink;
 struct GPUDrawObject;
+struct GridCommonGPUBuffer;
 struct PBVH;
 struct MVert;
 
@@ -160,9 +161,6 @@ void GPU_buffer_free(GPUBuffer *buffer);
 
 void GPU_drawobject_free(struct DerivedMesh *dm);
 
-/* free special global multires grid buffer */
-void GPU_buffer_multires_free(bool force);
-
 /* flag that controls data type to fill buffer with, a modifier will prepare. */
 typedef enum {
        GPU_BUFFER_VERTEX = 0,
@@ -231,8 +229,9 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
         const int *face_indices,
         const int  face_indices_len);
 
-GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
-                                    unsigned int **grid_hidden, int gridsize, const struct CCGKey *key);
+GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(
+        int *grid_indices, int totgrid,unsigned int **grid_hidden, int gridsize, const struct CCGKey *key,
+        struct GridCommonGPUBuffer **grid_common_gpu_buffer);
 
 GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(bool smooth_shading);
 
@@ -267,5 +266,6 @@ void GPU_init_draw_pbvh_BB(void);
 bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
 
 void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers);
+void GPU_free_pbvh_buffer_multires(struct GridCommonGPUBuffer **grid_common_gpu_buffer);
 
 #endif
index bd7a3b6..6214659 100644 (file)
@@ -107,10 +107,12 @@ static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
 static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
 
 /* multires global buffer, can be used for many grids having the same grid size */
-static GPUBuffer *mres_glob_buffer = NULL;
-static int mres_prev_gridsize = -1;
-static GLenum mres_prev_index_type = 0;
-static unsigned mres_prev_totquad = 0;
+typedef struct GridCommonGPUBuffer {
+       GPUBuffer *mres_buffer;
+       int mres_prev_gridsize;
+       GLenum mres_prev_index_type;
+       unsigned mres_prev_totquad;
+} GridCommonGPUBuffer;
 
 void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat)
 {
@@ -407,33 +409,6 @@ void GPU_buffer_free(GPUBuffer *buffer)
        BLI_mutex_unlock(&buffer_mutex);
 }
 
-void GPU_buffer_multires_free(bool force)
-{
-       if (!mres_glob_buffer) {
-               /* Early output, no need to lock in this case, */
-               return;
-       }
-
-       if (force && BLI_thread_is_main()) {
-               if (mres_glob_buffer) {
-                       if (mres_glob_buffer->id)
-                               glDeleteBuffers(1, &mres_glob_buffer->id);
-                       MEM_freeN(mres_glob_buffer);
-               }
-       }
-       else {
-               BLI_mutex_lock(&buffer_mutex);
-               gpu_buffer_free_intern(mres_glob_buffer);
-               BLI_mutex_unlock(&buffer_mutex);
-       }
-
-       mres_glob_buffer = NULL;
-       mres_prev_gridsize = -1;
-       mres_prev_index_type = 0;
-       mres_prev_totquad = 0;
-}
-
-
 void GPU_drawobject_free(DerivedMesh *dm)
 {
        GPUDrawObject *gdo;
@@ -1009,6 +984,7 @@ struct GPU_PBVH_Buffers {
        const int *grid_indices;
        int totgrid;
        bool has_hidden;
+       bool is_index_buf_global;  /* Means index_buf uses global bvh's grid_common_gpu_buffer, **DO NOT** free it! */
 
        bool use_bmesh;
 
@@ -1226,8 +1202,10 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
        /* An element index buffer is used for smooth shading, but flat
         * shading requires separate vertex normals so an index buffer is
         * can't be used there. */
-       if (buffers->smooth)
+       if (buffers->smooth) {
                buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3);
+               buffers->is_index_buf_global = false;
+       }
 
        if (buffers->index_buf) {
                /* Fill the triangle buffer */
@@ -1248,8 +1226,11 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
                        GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
                }
                else {
-                       GPU_buffer_free(buffers->index_buf);
+                       if (!buffers->is_index_buf_global) {
+                               GPU_buffer_free(buffers->index_buf);
+                       }
                        buffers->index_buf = NULL;
+                       buffers->is_index_buf_global = false;
                }
        }
 
@@ -1416,22 +1397,33 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
     } (void)0
 /* end FILL_QUAD_BUFFER */
 
-static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
+static GPUBuffer *gpu_get_grid_buffer(
+        int gridsize, GLenum *index_type, unsigned *totquad, GridCommonGPUBuffer **grid_common_gpu_buffer)
 {
        /* used in the FILL_QUAD_BUFFER macro */
        BLI_bitmap * const *grid_hidden = NULL;
        const int *grid_indices = NULL;
        int totgrid = 1;
 
+       GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
+
+       if (gridbuff == NULL) {
+               *grid_common_gpu_buffer = gridbuff = MEM_mallocN(sizeof(GridCommonGPUBuffer), __func__);
+               gridbuff->mres_buffer = NULL;
+               gridbuff->mres_prev_gridsize = -1;
+               gridbuff->mres_prev_index_type = 0;
+               gridbuff->mres_prev_totquad = 0;
+       }
+
        /* VBO is already built */
-       if (mres_glob_buffer && mres_prev_gridsize == gridsize) {
-               *index_type = mres_prev_index_type;
-               *totquad = mres_prev_totquad;
-               return mres_glob_buffer;
+       if (gridbuff->mres_buffer && gridbuff->mres_prev_gridsize == gridsize) {
+               *index_type = gridbuff->mres_prev_index_type;
+               *totquad = gridbuff->mres_prev_totquad;
+               return gridbuff->mres_buffer;
        }
        /* we can't reuse old, delete the existing buffer */
-       else if (mres_glob_buffer) {
-               GPU_buffer_free(mres_glob_buffer);
+       else if (gridbuff->mres_buffer) {
+               GPU_buffer_free(gridbuff->mres_buffer);
        }
 
        /* Build new VBO */
@@ -1439,17 +1431,17 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned
 
        if (gridsize * gridsize < USHRT_MAX) {
                *index_type = GL_UNSIGNED_SHORT;
-               FILL_QUAD_BUFFER(unsigned short, *totquad, mres_glob_buffer);
+               FILL_QUAD_BUFFER(unsigned short, *totquad, gridbuff->mres_buffer);
        }
        else {
                *index_type = GL_UNSIGNED_INT;
-               FILL_QUAD_BUFFER(unsigned int, *totquad, mres_glob_buffer);
+               FILL_QUAD_BUFFER(unsigned int, *totquad, gridbuff->mres_buffer);
        }
 
-       mres_prev_gridsize = gridsize;
-       mres_prev_index_type = *index_type;
-       mres_prev_totquad = *totquad;
-       return mres_glob_buffer;
+       gridbuff->mres_prev_gridsize = gridsize;
+       gridbuff->mres_prev_index_type = *index_type;
+       gridbuff->mres_prev_totquad = *totquad;
+       return gridbuff->mres_buffer;
 }
 
 #define FILL_FAST_BUFFER(type_) \
@@ -1476,8 +1468,9 @@ static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned
        } \
 } (void)0
 
-GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
-                                              BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key)
+GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(
+        int *grid_indices, int totgrid, BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key,
+        GridCommonGPUBuffer **grid_common_gpu_buffer)
 {
        GPU_PBVH_Buffers *buffers;
        int totquad;
@@ -1506,8 +1499,10 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
        }
 
        if (totquad == fully_visible_totquad) {
-               buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
+               buffers->index_buf = gpu_get_grid_buffer(
+                                        gridsize, &buffers->index_type, &buffers->tot_quad, grid_common_gpu_buffer);
                buffers->has_hidden = false;
+               buffers->is_index_buf_global = true;
        }
        else {
                buffers->tot_quad = totquad;
@@ -1522,6 +1517,7 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
                }
 
                buffers->has_hidden = true;
+               buffers->is_index_buf_global = false;
        }
 
        /* Build coord/normal VBO */
@@ -1746,8 +1742,9 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
                const int use_short = (maxvert < USHRT_MAX);
 
                /* Initialize triangle index buffer */
-               if (buffers->index_buf)
+               if (buffers->index_buf && !buffers->is_index_buf_global)
                        GPU_buffer_free(buffers->index_buf);
+               buffers->is_index_buf_global = false;
                buffers->index_buf = GPU_buffer_alloc((use_short ?
                                                      sizeof(unsigned short) :
                                                      sizeof(unsigned int)) * 3 * tottri);
@@ -1792,12 +1789,19 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
                }
                else {
                        /* Memory map failed */
-                       GPU_buffer_free(buffers->index_buf);
+                       if (!buffers->is_index_buf_global) {
+                               GPU_buffer_free(buffers->index_buf);
+                       }
                        buffers->index_buf = NULL;
+                       buffers->is_index_buf_global = false;
                }
        }
        else if (buffers->index_buf) {
-               GPU_buffer_free(buffers->index_buf);
+               if (!buffers->is_index_buf_global) {
+                       GPU_buffer_free(buffers->index_buf);
+               }
+               buffers->index_buf = NULL;
+               buffers->is_index_buf_global = false;
        }
 }
 
@@ -1993,7 +1997,7 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
        if (buffers) {
                if (buffers->vert_buf)
                        GPU_buffer_free(buffers->vert_buf);
-               if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
+               if (buffers->index_buf && !buffers->is_index_buf_global)
                        GPU_buffer_free(buffers->index_buf);
                if (buffers->index_buf_fast)
                        GPU_buffer_free(buffers->index_buf_fast);
@@ -2006,6 +2010,20 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
        }
 }
 
+void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer)
+{
+       GridCommonGPUBuffer *gridbuff = *grid_common_gpu_buffer;
+
+       if (gridbuff) {
+               if (gridbuff->mres_buffer) {
+                       BLI_mutex_lock(&buffer_mutex);
+                       gpu_buffer_free_intern(gridbuff->mres_buffer);
+                       BLI_mutex_unlock(&buffer_mutex);
+               }
+               MEM_freeN(gridbuff);
+               *grid_common_gpu_buffer = NULL;
+       }
+}
 
 /* debug function, draws the pbvh BB */
 void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
index da4dd65..8fed6a9 100644 (file)
@@ -73,7 +73,6 @@ void GPU_exit(void)
        gpu_codegen_exit();
 
        gpu_extensions_exit(); /* must come last */
-       GPU_buffer_multires_free(true);
 
        initialized = false;
 }
index cb51e16..5eb7afb 100644 (file)
@@ -142,7 +142,6 @@ typedef struct ID {
  */
 typedef struct Library {
        ID id;
-       ID *idblock;
        struct FileData *filedata;
        char name[1024];  /* path name used for reading, can be relative and edited in the outliner */
 
@@ -155,6 +154,9 @@ typedef struct Library {
        struct Library *parent; /* set for indirectly linked libs, used in the outliner and while reading */
        
        struct PackedFile *packedfile;
+
+       int temp_index;
+       int _pad;
 } Library;
 
 enum eIconSizes {
index fdad6aa..4c12834 100644 (file)
@@ -484,7 +484,7 @@ typedef struct FCurve {
        unsigned int totvert;   /* total number of points which define the curve (i.e. size of arrays in FPoints) */
        
                /* value cache + settings */
-       float curval;                   /* value stored from last time curve was evaluated */
+       float curval;                   /* value stored from last time curve was evaluated (not threadsafe, debug display only!) */
        short flag;                             /* user-editable settings for this curve */
        short extend;                   /* value-extending mode for this curve (does not cover  */
        
index 1818aee..5d04fba 100644 (file)
@@ -1480,7 +1480,9 @@ typedef struct NormalEditModifierData {
        short mix_mode;
        char pad[2];
        float mix_factor;
+       float mix_limit;
        float offset[3];
+       float pad_f1;
 } NormalEditModifierData;
 
 /* NormalEditModifierData.mode */
index 105b7f1..1ab52aa 100644 (file)
@@ -4480,6 +4480,11 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
                             "How much of generated normals to mix with exiting ones", 0.0f, 1.0f);
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
+       prop = RNA_def_float(srna, "mix_limit", 1.0f, 0.0f, DEG2RADF(180.0f), "Max Angle",
+                            "Maximum angle between old and new normals", 0.0f, DEG2RADF(180.0f));
+       RNA_def_property_subtype(prop, PROP_ANGLE);
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
        prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
        RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
        RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for selecting/weighting the affected areas");
index 00101f5..9c16f53 100644 (file)
@@ -2318,6 +2318,8 @@ static void rna_def_object(BlenderRNA *brna)
 
        prop = RNA_def_property(srna, "dimensions", PROP_FLOAT, PROP_XYZ_LENGTH);
        RNA_def_property_array(prop, 3);
+       /* only for the transform-panel and conflicts with animating scale */
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_float_funcs(prop, "rna_Object_dimensions_get", "rna_Object_dimensions_set", NULL);
        RNA_def_property_ui_range(prop, 0.0f, FLT_MAX, 1, 3);
        RNA_def_property_ui_text(prop, "Dimensions", "Absolute bounding box dimensions of the object");
index e1216e3..c3c6662 100644 (file)
@@ -151,9 +151,9 @@ static void rna_Scene_ray_cast(
 
        bool ret = ED_transform_snap_object_project_ray_ex(
                sctx,
+               SCE_SNAP_MODE_FACE,
                &(const struct SnapObjectParams){
                    .snap_select = SNAP_ALL,
-                   .snap_to = SCE_SNAP_MODE_FACE,
                },
                origin, direction, &ray_dist,
                r_location, r_normal, r_index,
index 7720e1a..2700535 100644 (file)
@@ -408,7 +408,7 @@ static void rna_userdef_addon_remove(ReportList *reports, PointerRNA *path_cmp_p
 {
        bAddon *bext = path_cmp_ptr->data;
        if (BLI_findindex(&U.addons, bext) == -1) {
-               BKE_report(reports, RPT_ERROR, "Addon is no longer valid");
+               BKE_report(reports, RPT_ERROR, "Add-on is no longer valid");
                return;
        }
 
@@ -705,7 +705,7 @@ static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void
 
        BLI_strncpy(dummyapt.idname, dummyaddon.module, sizeof(dummyapt.idname));
        if (strlen(identifier) >= sizeof(dummyapt.idname)) {
-               BKE_reportf(reports, RPT_ERROR, "Registering addon-prefs class: '%s' is too long, maximum length is %d",
+               BKE_reportf(reports, RPT_ERROR, "Registering add-on preferences class: '%s' is too long, maximum length is %d",
                            identifier, (int)sizeof(dummyapt.idname));
                return NULL;
        }
@@ -3195,7 +3195,7 @@ static void rna_def_userdef_addon(BlenderRNA *brna)
        srna = RNA_def_struct(brna, "Addon", NULL);
        RNA_def_struct_sdna(srna, "bAddon");
        RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
-       RNA_def_struct_ui_text(srna, "Addon", "Python addons to be loaded automatically");
+       RNA_def_struct_ui_text(srna, "Add-on", "Python add-ons to be loaded automatically");
 
        prop = RNA_def_property(srna, "module", PROP_STRING, PROP_NONE);
        RNA_def_property_ui_text(prop, "Module", "Module name");
@@ -3232,7 +3232,7 @@ static void rna_def_userdef_addon_pref(BlenderRNA *brna)
        PropertyRNA *prop;
 
        srna = RNA_def_struct(brna, "AddonPreferences", NULL);
-       RNA_def_struct_ui_text(srna, "Addon Preferences", "");
+       RNA_def_struct_ui_text(srna, "Add-on Preferences", "");
        RNA_def_struct_sdna(srna, "bAddon");  /* WARNING: only a bAddon during registration */
 
        RNA_def_struct_refine_func(srna, "rna_AddonPref_refine");
@@ -4596,7 +4596,7 @@ static void rna_def_userdef_filepaths(BlenderRNA *brna)
        RNA_def_property_string_sdna(prop, NULL, "pythondir");
        RNA_def_property_ui_text(prop, "Python Scripts Directory",
                                 "Alternate script path, matching the default layout with subdirs: "
-                                "startup, addons & modules (requires restart)");
+                                "startup, add-ons & modules (requires restart)");
        /* TODO, editing should reset sys.path! */
 
        prop = RNA_def_property(srna, "i18n_branches_directory", PROP_STRING, PROP_DIRPATH);
@@ -4688,7 +4688,7 @@ static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cpro
        func = RNA_def_function(srna, "remove", "rna_userdef_addon_remove");
        RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_REPORTS);
        RNA_def_function_ui_description(func, "Remove add-on");
-       parm = RNA_def_pointer(func, "addon", "Addon", "", "Addon to remove");
+       parm = RNA_def_pointer(func, "addon", "Addon", "", "Add-on to remove");
        RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL | PROP_RNAPTR);
        RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
 }
@@ -4764,7 +4764,7 @@ void RNA_def_userdef(BlenderRNA *brna)
        prop = RNA_def_property(srna, "addons", PROP_COLLECTION, PROP_NONE);
        RNA_def_property_collection_sdna(prop, NULL, "addons", NULL);
        RNA_def_property_struct_type(prop, "Addon");
-       RNA_def_property_ui_text(prop, "Addon", "");
+       RNA_def_property_ui_text(prop, "Add-on", "");
        rna_def_userdef_addon_collection(brna, prop);
 
        prop = RNA_def_property(srna, "autoexec_paths", PROP_COLLECTION, PROP_NONE);
index 355dd6d..d386653 100644 (file)
@@ -110,7 +110,7 @@ static void generate_vert_coordinates(
 /* Note this modifies nos_new in-place. */
 static void mix_normals(
         const float mix_factor, MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
-        const short mix_mode,
+        const float mix_limit, const short mix_mode,
         const int num_verts, MLoop *mloop, float (*nos_old)[3], float (*nos_new)[3], const int num_loops)
 {
        /* Mix with org normals... */
@@ -143,7 +143,9 @@ static void mix_normals(
                        case MOD_NORMALEDIT_MIX_COPY:
                                break;
                }
-               interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new, fac);
+
+               interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new,
+                                         (mix_limit < M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac);
        }
 
        MEM_SAFE_FREE(facs);
@@ -186,7 +188,7 @@ static bool polygons_check_flip(
 static void normalEditModifier_do_radial(
         NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
         short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
-        const short mix_mode, const float mix_factor,
+        const short mix_mode, const float mix_factor, const float mix_limit,
         MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
         MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
         MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
@@ -265,7 +267,7 @@ static void normalEditModifier_do_radial(
 
        if (loopnors) {
                mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
-                           mix_mode, num_verts, mloop, loopnors, nos, num_loops);
+                           mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
        }
 
        if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
@@ -283,7 +285,7 @@ static void normalEditModifier_do_radial(
 static void normalEditModifier_do_directional(
         NormalEditModifierData *smd, Object *ob, DerivedMesh *dm,
         short (*clnors)[2], float (*loopnors)[3], float (*polynors)[3],
-        const short mix_mode, const float mix_factor,
+        const short mix_mode, const float mix_factor, const float mix_limit,
         MDeformVert *dvert, const int defgrp_index, const bool use_invert_vgroup,
         MVert *mvert, const int num_verts, MEdge *medge, const int num_edges,
         MLoop *mloop, const int num_loops, MPoly *mpoly, const int num_polys)
@@ -342,7 +344,7 @@ static void normalEditModifier_do_directional(
 
        if (loopnors) {
                mix_normals(mix_factor, dvert, defgrp_index, use_invert_vgroup,
-                           mix_mode, num_verts, mloop, loopnors, nos, num_loops);
+                           mix_limit, mix_mode, num_verts, mloop, loopnors, nos, num_loops);
        }
 
        if (polygons_check_flip(mloop, nos, dm->getLoopDataLayout(dm), mpoly, polynors, num_polys)) {
@@ -384,7 +386,8 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o
        const bool use_invert_vgroup = ((smd->flag & MOD_NORMALEDIT_INVERT_VGROUP) != 0);
        const bool use_current_clnors = !((smd->mix_mode == MOD_NORMALEDIT_MIX_COPY) &&
                                          (smd->mix_factor == 1.0f) &&
-                                         (smd->defgrp_name[0] == '\0'));
+                                         (smd->defgrp_name[0] == '\0') &&
+                                         (smd->mix_limit == M_PI));
 
        int defgrp_index;
        MDeformVert *dvert;
@@ -439,13 +442,13 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o
        if (smd->mode == MOD_NORMALEDIT_MODE_RADIAL) {
                normalEditModifier_do_radial(
                            smd, ob, dm, clnors, loopnors, polynors,
-                           smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
+                           smd->mix_mode, smd->mix_factor, smd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
                            mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
        }
        else if (smd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) {
                normalEditModifier_do_directional(
                            smd, ob, dm, clnors, loopnors, polynors,
-                           smd->mix_mode, smd->mix_factor, dvert, defgrp_index, use_invert_vgroup,
+                           smd->mix_mode, smd->mix_factor, smd->mix_limit, dvert, defgrp_index, use_invert_vgroup,
                            mvert, num_verts, medge, num_edges, mloop, num_loops, mpoly, num_polys);
        }
 
@@ -464,6 +467,7 @@ static void initData(ModifierData *md)
 
        smd->mix_mode = MOD_NORMALEDIT_MIX_COPY;
        smd->mix_factor = 1.0f;
+       smd->mix_limit = M_PI;
 }
 
 static void copyData(ModifierData *md, ModifierData *target)
index a4d4652..4ccf9fa 100644 (file)
@@ -124,6 +124,7 @@ ModifierTypeInfo modifierType_ShapeKey = {
        /* structSize */        sizeof(ShapeKeyModifierData),
        /* type */              eModifierTypeType_OnlyDeform,
        /* flags */             eModifierTypeFlag_AcceptsCVs |
+                               eModifierTypeFlag_AcceptsLattice |
                                eModifierTypeFlag_SupportsEditmode,
 
        /* copyData */          NULL,
index 3607e66..1935e4e 100644 (file)
@@ -38,6 +38,8 @@
 extern "C" {
 #endif
 
+#include "BLI_math_geom.h"
+
 struct RayObject;
 
 /* Ray Hints */
@@ -101,6 +103,9 @@ typedef struct Isect {
 #ifdef RE_RAYCOUNTER
        RayCounter *raycounter;
 #endif
+
+       /* Precalculated coefficients for watertight intersection check. */
+       struct IsectRayPrecalc isect_precalc;
 } Isect;
 
 /* ray types */
index de6b913..f511042 100644 (file)
@@ -138,80 +138,29 @@ MALWAYS_INLINE int vlr_check_bake(Isect *is, ObjectInstanceRen *obi, VlakRen *UN
 
 /* Ray Triangle/Quad Intersection */
 
-MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, float uv[2], float *lambda)
+MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *isect_precalc, RayFace *face, float r_uv[2], float *lambda)
 {
-       float co1[3], co2[3], co3[3], co4[3];
-       float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1, l;
-       int quad;
-
-       quad = RE_rayface_isQuad(face);
-
-       copy_v3_v3(co1, face->v1);
-       copy_v3_v3(co2, face->v2);
-       copy_v3_v3(co3, face->v3);
-
-       copy_v3_v3(r, dir);
-
-       /* intersect triangle */
-       sub_v3_v3v3(t0, co3, co2);
-       sub_v3_v3v3(t1, co3, co1);
-
-       cross_v3_v3v3(x, r, t1);
-       divdet = dot_v3v3(t0, x);
-
-       sub_v3_v3v3(m, start, co3);
-       det1 = dot_v3v3(m, x);
-       
-       if (divdet != 0.0f) {
-               divdet = 1.0f / divdet;
-               v = det1 * divdet;
-
-               if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                       float cros[3];
-
-                       cross_v3_v3v3(cros, m, t0);
-                       u = divdet * dot_v3v3(cros, r);
-
-                       if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                               l = divdet * dot_v3v3(cros, t1);
-
-                               /* check if intersection is within ray length */
-                               if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
-                                       uv[0] = u;
-                                       uv[1] = v;
-                                       *lambda = l;
-                                       return 1;
-                               }
-                       }
+       float uv[2], l;
+
+       if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) {
+               /* check if intersection is within ray length */
+               if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
+                       r_uv[0] = uv[0];
+                       r_uv[1] = uv[1];
+                       *lambda = l;
+                       return 1;
                }
        }
 
        /* intersect second triangle in quad */
-       if (quad) {
-               copy_v3_v3(co4, face->v4);
-               sub_v3_v3v3(t0, co3, co4);
-               divdet = dot_v3v3(t0, x);
-
-               if (divdet != 0.0f) {
-                       divdet = 1.0f / divdet;
-                       v = det1 * divdet;
-                       
-                       if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                               float cros[3];
-
-                               cross_v3_v3v3(cros, m, t0);
-                               u = divdet * dot_v3v3(cros, r);
-       
-                               if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                                       l = divdet * dot_v3v3(cros, t1);
-                                       
-                                       if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
-                                               uv[0] = u;
-                                               uv[1] = -(1.0f + v + u);
-                                               *lambda = l;
-                                               return 2;
-                                       }
-                               }
+       if (RE_rayface_isQuad(face)) {
+               if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) {
+                       /* check if intersection is within ray length */
+                       if (l > -RE_RAYTRACE_EPSILON && l < *lambda) {
+                               r_uv[0] = uv[0];
+                               r_uv[1] = uv[1];
+                               *lambda = l;
+                               return 2;
                        }
                }
        }
@@ -223,62 +172,23 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], float dir[3], RayFace *face, fl
 
 MALWAYS_INLINE int isec_tri_quad_neighbour(float start[3], float dir[3], RayFace *face)
 {
-       float co1[3], co2[3], co3[3], co4[3];
-       float t0[3], t1[3], x[3], r[3], m[3], u, v, divdet, det1;
-       int quad;
-
-       quad = RE_rayface_isQuad(face);
+       float r[3];
+       struct IsectRayPrecalc isect_precalc;
+       float uv[2], l;
 
-       copy_v3_v3(co1, face->v1);
-       copy_v3_v3(co2, face->v2);
-       copy_v3_v3(co3, face->v3);
 
        negate_v3_v3(r, dir); /* note, different than above function */
 
-       /* intersect triangle */
-       sub_v3_v3v3(t0, co3, co2);
-       sub_v3_v3v3(t1, co3, co1);
-
-       cross_v3_v3v3(x, r, t1);
-       divdet = dot_v3v3(t0, x);
-
-       sub_v3_v3v3(m, start, co3);
-       det1 = dot_v3v3(m, x);
-       
-       if (divdet != 0.0f) {
-               divdet = 1.0f / divdet;
-               v = det1 * divdet;
-
-               if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                       float cros[3];
-
-                       cross_v3_v3v3(cros, m, t0);
-                       u = divdet * dot_v3v3(cros, r);
+       isect_ray_tri_watertight_v3_precalc(&isect_precalc, r);
 
-                       if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON))
-                               return 1;
-               }
+       if (isect_ray_tri_watertight_v3(start, &isect_precalc, face->v1, face->v2, face->v3, &l, uv)) {
+               return 1;
        }
 
        /* intersect second triangle in quad */
-       if (quad) {
-               copy_v3_v3(co4, face->v4);
-               sub_v3_v3v3(t0, co3, co4);
-               divdet = dot_v3v3(t0, x);
-
-               if (divdet != 0.0f) {
-                       divdet = 1.0f / divdet;
-                       v = det1 * divdet;
-                       
-                       if (v < RE_RAYTRACE_EPSILON && v > -(1.0f + RE_RAYTRACE_EPSILON)) {
-                               float cros[3];
-
-                               cross_v3_v3v3(cros, m, t0);
-                               u = divdet * dot_v3v3(cros, r);
-       
-                               if (u < RE_RAYTRACE_EPSILON && (v + u) > -(1.0f + RE_RAYTRACE_EPSILON))
-                                       return 2;
-                       }
+       if (RE_rayface_isQuad(face)) {
+               if (isect_ray_tri_watertight_v3(start, &isect_precalc, face->v1, face->v3, face->v4, &l, uv)) {
+                       return 2;
                }
        }
 
@@ -317,7 +227,7 @@ MALWAYS_INLINE int intersect_rayface(RayObject *hit_obj, RayFace *face, Isect *i
        RE_RC_COUNT(is->raycounter->faces.test);
 
        dist = is->dist;
-       ok = isec_tri_quad(is->start, is->dir, face, uv, &dist);
+       ok = isec_tri_quad(is->start, &is->isect_precalc, face, uv, &dist);
 
        if (ok) {
        
@@ -389,6 +299,9 @@ int RE_rayobject_raycast(RayObject *r, Isect *isec)
 {
        int i;
 
+       /* Pre-calculate orientation for watertight intersection checks. */
+       isect_ray_tri_watertight_v3_precalc(&isec->isect_precalc, isec->dir);
+
        RE_RC_COUNT(isec->raycounter->raycast.test);
 
        /* setup vars used on raycast */
index 2d26fcf..bddd84c 100644 (file)
@@ -359,102 +359,109 @@ static const char *name_from_passtype(int passtype, int channel)
        return "Unknown";
 }
 
-static int passtype_from_name(const char *str)
+static int passtype_from_name(const char *str, int passflag)
 {
+       /* We do not really support several pass of the same types, so in case we are opening an EXR file with several pass
+        * names detected as same pass type, only return that pass type the first time, and return 'uknown' for the others.
+        * See T48466. */
+#define RETURN_PASS(_passtype) return (passflag & (_passtype)) ? 0 : (_passtype)
+
        if (STRPREFIX(str, "Combined"))
-               return SCE_PASS_COMBINED;
+               RETURN_PASS(SCE_PASS_COMBINED);
 
        if (STRPREFIX(str, "Depth"))
-               return SCE_PASS_Z;
+               RETURN_PASS(SCE_PASS_Z);
 
        if (STRPREFIX(str, "Vector"))
-               return SCE_PASS_VECTOR;
+               RETURN_PASS(SCE_PASS_VECTOR);
 
        if (STRPREFIX(str, "Normal"))
-               return SCE_PASS_NORMAL;
+               RETURN_PASS(SCE_PASS_NORMAL);
 
        if (STRPREFIX(str, "UV"))
-               return SCE_PASS_UV;
+               RETURN_PASS(SCE_PASS_UV);
 
        if (STRPREFIX(str, "Color"))
-               return SCE_PASS_RGBA;
+               RETURN_PASS(SCE_PASS_RGBA);
 
        if (STRPREFIX(str, "Emit"))
-               return SCE_PASS_EMIT;
+               RETURN_PASS(SCE_PASS_EMIT);
 
        if (STRPREFIX(str, "Diffuse"))
-               return SCE_PASS_DIFFUSE;
+               RETURN_PASS(SCE_PASS_DIFFUSE);
 
        if (STRPREFIX(str, "Spec"))
-               return SCE_PASS_SPEC;
+               RETURN_PASS(SCE_PASS_SPEC);
 
        if (STRPREFIX(str, "Shadow"))
-               return SCE_PASS_SHADOW;
+               RETURN_PASS(SCE_PASS_SHADOW);
        
        if (STRPREFIX(str, "AO"))
-               return SCE_PASS_AO;
+               RETURN_PASS(SCE_PASS_AO);
 
        if (STRPREFIX(str, "Env"))
-               return SCE_PASS_ENVIRONMENT;
+               RETURN_PASS(SCE_PASS_ENVIRONMENT);
 
        if (STRPREFIX(str, "Indirect"))
-               return SCE_PASS_INDIRECT;
+               RETURN_PASS(SCE_PASS_INDIRECT);
 
        if (STRPREFIX(str, "Reflect"))
-               return SCE_PASS_REFLECT;
+               RETURN_PASS(SCE_PASS_REFLECT);
 
        if (STRPREFIX(str, "Refract"))
-               return SCE_PASS_REFRACT;
+               RETURN_PASS(SCE_PASS_REFRACT);
 
        if (STRPREFIX(str, "IndexOB"))
-               return SCE_PASS_INDEXOB;
+               RETURN_PASS(SCE_PASS_INDEXOB);
 
        if (STRPREFIX(str, "IndexMA"))
-               return SCE_PASS_INDEXMA;
+               RETURN_PASS(SCE_PASS_INDEXMA);
 
        if (STRPREFIX(str, "Mist"))
-               return SCE_PASS_MIST;
+               RETURN_PASS(SCE_PASS_MIST);
        
        if (STRPREFIX(str, "RayHits"))
-               return SCE_PASS_RAYHITS;
+               RETURN_PASS(SCE_PASS_RAYHITS);
 
        if (STRPREFIX(str, "DiffDir"))
-               return SCE_PASS_DIFFUSE_DIRECT;
+               RETURN_PASS(SCE_PASS_DIFFUSE_DIRECT);
 
        if (STRPREFIX(str, "DiffInd"))
-               return SCE_PASS_DIFFUSE_INDIRECT;
+               RETURN_PASS(SCE_PASS_DIFFUSE_INDIRECT);
 
        if (STRPREFIX(str, "DiffCol"))
-               return SCE_PASS_DIFFUSE_COLOR;
+               RETURN_PASS(SCE_PASS_DIFFUSE_COLOR);
 
        if (STRPREFIX(str, "GlossDir"))
-               return SCE_PASS_GLOSSY_DIRECT;
+               RETURN_PASS(SCE_PASS_GLOSSY_DIRECT);
 
        if (STRPREFIX(str, "GlossInd"))
-               return SCE_PASS_GLOSSY_INDIRECT;
+               RETURN_PASS(SCE_PASS_GLOSSY_INDIRECT);
 
        if (STRPREFIX(str, "GlossCol"))
-               return SCE_PASS_GLOSSY_COLOR;
+               RETURN_PASS(SCE_PASS_GLOSSY_COLOR);
 
        if (STRPREFIX(str, "TransDir"))
-               return SCE_PASS_TRANSM_DIRECT;
+               RETURN_PASS(SCE_PASS_TRANSM_DIRECT);
 
        if (STRPREFIX(str, "TransInd"))
-               return SCE_PASS_TRANSM_INDIRECT;
+               RETURN_PASS(SCE_PASS_TRANSM_INDIRECT);
 
        if (STRPREFIX(str, "TransCol"))
-               return SCE_PASS_TRANSM_COLOR;
+               RETURN_PASS(SCE_PASS_TRANSM_COLOR);
                
        if (STRPREFIX(str, "SubsurfaceDir"))
-               return SCE_PASS_SUBSURFACE_DIRECT;
+               RETURN_PASS(SCE_PASS_SUBSURFACE_DIRECT);
 
        if (STRPREFIX(str, "SubsurfaceInd"))
-               return SCE_PASS_SUBSURFACE_INDIRECT;
+               RETURN_PASS(SCE_PASS_SUBSURFACE_INDIRECT);
 
        if (STRPREFIX(str, "SubsurfaceCol"))
-               return SCE_PASS_SUBSURFACE_COLOR;
+               RETURN_PASS(SCE_PASS_SUBSURFACE_COLOR);
 
        return 0;
+
+#undef RETURN_PASS
 }
 
 
@@ -838,8 +845,9 @@ static void ml_addpass_cb(void *base, void *lay, const char *str, float *rect, i
        
        BLI_addtail(&rl->passes, rpass);
        rpass->channels = totchan;
-       rpass->passtype = passtype_from_name(str);
-       if (rpass->passtype == 0) printf("unknown pass %s\n", str);
+       rpass->passtype = passtype_from_name(str, rl->passflag);
+       if (rpass->passtype == 0)
+               printf("unknown pass %s\n", str);
        rl->passflag |= rpass->passtype;
        
        /* channel id chars */
index 36b819d..729af73 100644 (file)
@@ -435,8 +435,7 @@ void wm_file_read_report(bContext *C)
                        }
 
                        BKE_reportf(reports, RPT_ERROR,
-                                   "Engine '%s' not available for scene '%s' "
-                                   "(an addon may need to be installed or enabled)",
+                                   "Engine '%s' not available for scene '%s' (an add-on may need to be installed or enabled)",
                                    sce->r.engine, sce->id.name + 2);
                }
        }
index 6762e67..3a577ca 100644 (file)
@@ -525,6 +525,7 @@ SnapObjectContext *ED_transform_snap_object_context_create_view3d(
 void ED_transform_snap_object_context_destroy(SnapObjectContext *sctx) RET_NONE
 bool ED_transform_snap_object_project_ray_ex(
         struct SnapObjectContext *sctx,
+        const unsigned short snap_to,
         const struct SnapObjectParams *params,
         const float ray_start[3], const float ray_normal[3], float *ray_depth,
         /* return args */
index e3cbfbf..122c10e 100644 (file)
@@ -692,6 +692,10 @@ elseif(WIN32)
                        )
 
                        if(WITH_PYTHON_INSTALL_NUMPY)
+                               set(PYTHON_NUMPY_VERSION 1.9)
+                               if(MSVC_VERSION EQUAL 1900)
+                                       set(PYTHON_NUMPY_VERSION 1.11)
+                               endif()
                                add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
                                        COMMAND ${CMAKE_COMMAND} -E
                                                make_directory ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages)
@@ -699,9 +703,9 @@ elseif(WIN32)
                                add_custom_command(
                                        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages/numpy
                                        COMMAND ${CMAKE_COMMAND} -E
-                                               tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz"
+                                               tar xzvf "${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz"
                                        DEPENDS
-                                               ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_1.9.tar.gz
+                                               ${LIBDIR}/release/python${_PYTHON_VERSION_NO_DOTS}_numpy_${PYTHON_NUMPY_VERSION}.tar.gz
                                                ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
                                        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${BLENDER_VERSION}/python/lib/site-packages
                                )
index 69765fc..3b27ad6 100644 (file)
@@ -583,9 +583,16 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
 
        BLI_argsPrintArgDoc(ba, "--");
 
+       printf("\n");
        printf("Other Options:\n");
        BLI_argsPrintOtherDoc(ba);
 
+       /* keep last args */
+       printf("\n");
+       printf("Experimental Features:\n");
+       BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph");
+
+       printf("\n");
        printf("Argument Parsing:\n");
        printf("\tArguments must be separated by white space, eg:\n");
        printf("\t# blender -ba test.blend\n");
@@ -619,11 +626,6 @@ static int arg_handle_print_help(int UNUSED(argc), const char **UNUSED(argv), vo
 #endif
        printf("  $PYTHONHOME               Path to the python directory, eg. /usr/lib/python.\n\n");
 
-       /* keep last */
-       printf("\n");
-       printf("Experimental Features:\n");
-       BLI_argsPrintArgDoc(ba, "--enable-new-depsgraph");
-
        exit(0);
 
        return 0;
@@ -862,7 +864,7 @@ static const char arg_handle_playback_mode_doc[] =
 "<options> <file(s)>\n"
 "\tPlayback <file(s)>, only operates this way when not running in background.\n"
 "\t\t-p <sx> <sy>\tOpen with lower left corner at <sx>, <sy>\n"
-"\t\t-m\t\tRead from disk (Don't buffer)\n"
+"\t\t-m\t\tRead from disk (Do not buffer)\n"
 "\t\t-f <fps> <fps-base>\t\tSpecify FPS to start with\n"
 "\t\t-j <frame>\tSet frame step to <frame>\n"
 "\t\t-s <frame>\tPlay from <frame>\n"
@@ -950,10 +952,10 @@ static int arg_handle_start_with_console(int UNUSED(argc), const char **UNUSED(a
 }
 
 static const char arg_handle_register_extension_doc[] =
-"\n\tRegister .blend extension, then exit (Windows only)"
+"\n\tRegister blend-file extension, then exit (Windows only)"
 ;
 static const char arg_handle_register_extension_doc_silent[] =
-"\n\tSilently register .blend extension, then exit (Windows only)"
+"\n\tSilently register blend-file extension, then exit (Windows only)"
 ;
 static int arg_handle_register_extension(int UNUSED(argc), const char **UNUSED(argv), void *data)
 {