Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2017-04-04 22:39:57 +0300
committerJulian Eisel <eiseljulian@gmail.com>2017-04-04 22:39:57 +0300
commit7576ad3d043ac5d15e0c5a68e65339904441b5e7 (patch)
treebb990cce1eec04d45ab57e8a42af2669f9d7522f
parent10b24eabbab0193f6944cdf3bec7b386c75d5445 (diff)
parentdb0f67f46454fd0bfeb886d3e61227b65fbc6ac1 (diff)
Merge branch 'blender2.8' into transform-manipulatorstransform-manipulators
Conflicts: intern/gawain/gawain/immediate.h intern/gawain/src/immediate.c source/blender/editors/physics/physics_ops.c source/blender/editors/screen/glutil.c source/blender/editors/space_view3d/space_view3d.c source/blender/editors/space_view3d/view3d_draw.c source/blender/editors/space_view3d/view3d_edit.c source/blender/editors/space_view3d/view3d_ops.c source/blender/editors/transform/transform_manipulator.c
-rw-r--r--.gitmodules8
-rw-r--r--CMakeLists.txt39
-rw-r--r--GNUmakefile8
-rwxr-xr-xbuild_files/build_environment/install_deps.sh15
-rw-r--r--build_files/buildbot/master.cfg32
-rw-r--r--build_files/buildbot/master_unpack.py3
-rw-r--r--build_files/buildbot/slave_compile.py3
-rw-r--r--build_files/buildbot/slave_pack.py6
-rw-r--r--build_files/cmake/buildinfo.cmake2
-rw-r--r--build_files/cmake/macros.cmake20
-rw-r--r--build_files/cmake/packaging.cmake13
-rw-r--r--build_files/cmake/platform/platform_apple.cmake2
-rw-r--r--build_files/cmake/platform/platform_win32_msvc.cmake2
-rw-r--r--doc/python_api/examples/gpu.offscreen.1.py2
-rw-r--r--doc/python_api/rst/bge.texture.rst8
-rw-r--r--doc/python_api/sphinx_doc_gen.py8
-rwxr-xr-xdoc/python_api/sphinx_doc_update.py32
-rw-r--r--extern/clew/README.blender2
-rw-r--r--extern/clew/include/clew.h31
-rw-r--r--extern/clew/src/clew.c4
-rw-r--r--extern/cuew/include/cuew.h2
-rw-r--r--intern/CMakeLists.txt3
-rw-r--r--intern/atomic/atomic_ops.h10
-rw-r--r--intern/atomic/intern/atomic_ops_ext.h40
-rw-r--r--intern/audaspace/intern/AUD_SoftwareDevice.cpp1
-rw-r--r--intern/cycles/CMakeLists.txt7
-rw-r--r--intern/cycles/app/CMakeLists.txt10
-rw-r--r--intern/cycles/app/cycles_server.cpp18
-rw-r--r--intern/cycles/app/cycles_standalone.cpp38
-rw-r--r--intern/cycles/app/cycles_xml.cpp50
-rw-r--r--intern/cycles/blender/CMakeLists.txt8
-rw-r--r--intern/cycles/blender/addon/__init__.py15
-rw-r--r--intern/cycles/blender/addon/engine.py51
-rw-r--r--intern/cycles/blender/addon/presets.py15
-rw-r--r--intern/cycles/blender/addon/properties.py10
-rw-r--r--intern/cycles/blender/addon/ui.py82
-rw-r--r--intern/cycles/blender/blender_camera.cpp10
-rw-r--r--intern/cycles/blender/blender_curves.cpp38
-rw-r--r--intern/cycles/blender/blender_logging.cpp4
-rw-r--r--intern/cycles/blender/blender_mesh.cpp255
-rw-r--r--intern/cycles/blender/blender_object.cpp43
-rw-r--r--intern/cycles/blender/blender_object_cull.cpp4
-rw-r--r--intern/cycles/blender/blender_object_cull.h4
-rw-r--r--intern/cycles/blender/blender_particles.cpp12
-rw-r--r--intern/cycles/blender/blender_python.cpp77
-rw-r--r--intern/cycles/blender/blender_session.cpp76
-rw-r--r--intern/cycles/blender/blender_session.h15
-rw-r--r--intern/cycles/blender/blender_shader.cpp70
-rw-r--r--intern/cycles/blender/blender_sync.cpp46
-rw-r--r--intern/cycles/blender/blender_sync.h14
-rw-r--r--intern/cycles/blender/blender_texture.cpp2
-rw-r--r--intern/cycles/blender/blender_texture.h2
-rw-r--r--intern/cycles/blender/blender_util.h63
-rw-r--r--intern/cycles/bvh/CMakeLists.txt8
-rw-r--r--intern/cycles/bvh/bvh.cpp172
-rw-r--r--intern/cycles/bvh/bvh.h14
-rw-r--r--intern/cycles/bvh/bvh_binning.cpp8
-rw-r--r--intern/cycles/bvh/bvh_binning.h6
-rw-r--r--intern/cycles/bvh/bvh_build.cpp115
-rw-r--r--intern/cycles/bvh/bvh_build.h16
-rw-r--r--intern/cycles/bvh/bvh_node.cpp44
-rw-r--r--intern/cycles/bvh/bvh_node.h74
-rw-r--r--intern/cycles/bvh/bvh_params.h5
-rw-r--r--intern/cycles/bvh/bvh_sort.cpp10
-rw-r--r--intern/cycles/bvh/bvh_split.cpp12
-rw-r--r--intern/cycles/bvh/bvh_split.h4
-rw-r--r--intern/cycles/bvh/bvh_unaligned.cpp14
-rw-r--r--intern/cycles/bvh/bvh_unaligned.h2
-rw-r--r--intern/cycles/device/CMakeLists.txt10
-rw-r--r--intern/cycles/device/device.cpp32
-rw-r--r--intern/cycles/device/device.h38
-rw-r--r--intern/cycles/device/device_cpu.cpp394
-rw-r--r--intern/cycles/device/device_cuda.cpp386
-rw-r--r--intern/cycles/device/device_memory.h47
-rw-r--r--intern/cycles/device/device_multi.cpp26
-rw-r--r--intern/cycles/device/device_network.cpp20
-rw-r--r--intern/cycles/device/device_network.h10
-rw-r--r--intern/cycles/device/device_opencl.cpp8
-rw-r--r--intern/cycles/device/device_split_kernel.cpp306
-rw-r--r--intern/cycles/device/device_split_kernel.h132
-rw-r--r--intern/cycles/device/device_task.cpp8
-rw-r--r--intern/cycles/device/device_task.h10
-rw-r--r--intern/cycles/device/opencl/opencl.h138
-rw-r--r--intern/cycles/device/opencl/opencl_base.cpp111
-rw-r--r--intern/cycles/device/opencl/opencl_mega.cpp17
-rw-r--r--intern/cycles/device/opencl/opencl_split.cpp1483
-rw-r--r--intern/cycles/device/opencl/opencl_util.cpp404
-rw-r--r--intern/cycles/graph/CMakeLists.txt3
-rw-r--r--intern/cycles/graph/node.cpp10
-rw-r--r--intern/cycles/graph/node.h8
-rw-r--r--intern/cycles/graph/node_enum.h4
-rw-r--r--intern/cycles/graph/node_type.cpp6
-rw-r--r--intern/cycles/graph/node_type.h10
-rw-r--r--intern/cycles/graph/node_xml.cpp8
-rw-r--r--intern/cycles/graph/node_xml.h8
-rw-r--r--intern/cycles/kernel/CMakeLists.txt141
-rw-r--r--intern/cycles/kernel/bvh/bvh.h127
-rw-r--r--intern/cycles/kernel/bvh/bvh_nodes.h178
-rw-r--r--intern/cycles/kernel/bvh/bvh_shadow_all.h35
-rw-r--r--intern/cycles/kernel/bvh/bvh_subsurface.h25
-rw-r--r--intern/cycles/kernel/bvh/bvh_traversal.h17
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume.h19
-rw-r--r--intern/cycles/kernel/bvh/bvh_volume_all.h20
-rw-r--r--intern/cycles/kernel/bvh/qbvh_shadow_all.h30
-rw-r--r--intern/cycles/kernel/bvh/qbvh_subsurface.h23
-rw-r--r--intern/cycles/kernel/bvh/qbvh_traversal.h17
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume.h17
-rw-r--r--intern/cycles/kernel/bvh/qbvh_volume_all.h17
-rw-r--r--intern/cycles/kernel/closure/alloc.h22
-rw-r--r--intern/cycles/kernel/closure/bsdf.h162
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet.h2
-rw-r--r--intern/cycles/kernel/closure/bsdf_microfacet_multi.h10
-rw-r--r--intern/cycles/kernel/geom/geom.h26
-rw-r--r--intern/cycles/kernel/geom/geom_attribute.h8
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h136
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle_intersect.h53
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle_shader.h36
-rw-r--r--intern/cycles/kernel/geom/geom_object.h100
-rw-r--r--intern/cycles/kernel/geom/geom_patch.h6
-rw-r--r--intern/cycles/kernel/geom/geom_primitive.h36
-rw-r--r--intern/cycles/kernel/geom/geom_subd_triangle.h48
-rw-r--r--intern/cycles/kernel/geom/geom_triangle.h40
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h396
-rw-r--r--intern/cycles/kernel/geom/geom_volume.h4
-rw-r--r--intern/cycles/kernel/kernel.h16
-rw-r--r--intern/cycles/kernel/kernel_accumulate.h128
-rw-r--r--intern/cycles/kernel/kernel_bake.h3
-rw-r--r--intern/cycles/kernel/kernel_camera.h4
-rw-r--r--intern/cycles/kernel/kernel_compat_cpu.h27
-rw-r--r--intern/cycles/kernel/kernel_compat_cuda.h55
-rw-r--r--intern/cycles/kernel/kernel_compat_opencl.h14
-rw-r--r--intern/cycles/kernel/kernel_emission.h29
-rw-r--r--intern/cycles/kernel/kernel_globals.h26
-rw-r--r--intern/cycles/kernel/kernel_math.h12
-rw-r--r--intern/cycles/kernel/kernel_passes.h22
-rw-r--r--intern/cycles/kernel/kernel_path.h265
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h62
-rw-r--r--intern/cycles/kernel/kernel_path_common.h4
-rw-r--r--intern/cycles/kernel/kernel_path_state.h6
-rw-r--r--intern/cycles/kernel/kernel_path_subsurface.h187
-rw-r--r--intern/cycles/kernel/kernel_path_surface.h101
-rw-r--r--intern/cycles/kernel/kernel_path_volume.h34
-rw-r--r--intern/cycles/kernel/kernel_queues.h36
-rw-r--r--intern/cycles/kernel/kernel_random.h47
-rw-r--r--intern/cycles/kernel/kernel_shader.h369
-rw-r--r--intern/cycles/kernel/kernel_shadow.h661
-rw-r--r--intern/cycles/kernel/kernel_subsurface.h37
-rw-r--r--intern/cycles/kernel/kernel_textures.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h175
-rw-r--r--intern/cycles/kernel/kernel_volume.h81
-rw-r--r--intern/cycles/kernel/kernel_work_stealing.h211
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu.h40
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h113
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split.cpp63
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp38
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp40
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp34
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp36
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp37
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp6
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel.cu139
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_config.h110
-rw-r--r--intern/cycles/kernel/kernels/cuda/kernel_split.cu144
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel.cl90
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl125
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl27
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_data_init.cl70
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl70
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl110
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl64
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl97
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_path_init.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl93
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl64
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl51
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl65
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl26
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_split.cl35
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_state_buffer_size.cl29
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl27
-rw-r--r--intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl38
-rw-r--r--intern/cycles/kernel/osl/CMakeLists.txt8
-rw-r--r--intern/cycles/kernel/osl/background.cpp6
-rw-r--r--intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp12
-rw-r--r--intern/cycles/kernel/osl/bsdf_phong_ramp.cpp10
-rw-r--r--intern/cycles/kernel/osl/emissive.cpp10
-rw-r--r--intern/cycles/kernel/osl/osl_bssrdf.cpp20
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp55
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h4
-rw-r--r--intern/cycles/kernel/osl/osl_globals.h8
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp55
-rw-r--r--intern/cycles/kernel/osl/osl_shader.cpp23
-rw-r--r--intern/cycles/kernel/osl/osl_shader.h2
-rw-r--r--intern/cycles/kernel/split/kernel_background_buffer_update.h248
-rw-r--r--intern/cycles/kernel/split/kernel_buffer_update.h206
-rw-r--r--intern/cycles/kernel/split/kernel_data_init.h261
-rw-r--r--intern/cycles/kernel/split/kernel_direct_lighting.h163
-rw-r--r--intern/cycles/kernel/split/kernel_do_volume.h95
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h268
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_background.h82
-rw-r--r--intern/cycles/kernel/split/kernel_indirect_subsurface.h77
-rw-r--r--intern/cycles/kernel/split/kernel_lamp_emission.h82
-rw-r--r--intern/cycles/kernel/split/kernel_next_iteration_setup.h183
-rw-r--r--intern/cycles/kernel/split/kernel_path_init.h105
-rw-r--r--intern/cycles/kernel/split/kernel_queue_enqueue.h90
-rw-r--r--intern/cycles/kernel/split/kernel_scene_intersect.h116
-rw-r--r--intern/cycles/kernel/split/kernel_shader_eval.h91
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked.h85
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_ao.h60
-rw-r--r--intern/cycles/kernel/split/kernel_shadow_blocked_dl.h59
-rw-r--r--intern/cycles/kernel/split/kernel_split_common.h69
-rw-r--r--intern/cycles/kernel/split/kernel_split_data.h75
-rw-r--r--intern/cycles/kernel/split/kernel_split_data_types.h127
-rw-r--r--intern/cycles/kernel/split/kernel_subsurface_scatter.h100
-rw-r--r--intern/cycles/kernel/split/kernel_sum_all_radiance.h59
-rw-r--r--intern/cycles/kernel/svm/svm.h86
-rw-r--r--intern/cycles/kernel/svm/svm_attribute.h2
-rw-r--r--intern/cycles/kernel/svm/svm_bump.h18
-rw-r--r--intern/cycles/kernel/svm/svm_camera.h2
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h142
-rw-r--r--intern/cycles/kernel/svm/svm_displace.h10
-rw-r--r--intern/cycles/kernel/svm/svm_fresnel.h14
-rw-r--r--intern/cycles/kernel/svm/svm_geometry.h42
-rw-r--r--intern/cycles/kernel/svm/svm_image.h5
-rw-r--r--intern/cycles/kernel/svm/svm_light_path.h10
-rw-r--r--intern/cycles/kernel/svm/svm_noisetex.h46
-rw-r--r--intern/cycles/kernel/svm/svm_tex_coord.h112
-rw-r--r--intern/cycles/kernel/svm/svm_vector_transform.h2
-rw-r--r--intern/cycles/kernel/svm/svm_voxel.h2
-rw-r--r--intern/cycles/kernel/svm/svm_wireframe.h28
-rw-r--r--intern/cycles/render/CMakeLists.txt10
-rw-r--r--intern/cycles/render/attribute.cpp12
-rw-r--r--intern/cycles/render/attribute.h10
-rw-r--r--intern/cycles/render/background.cpp22
-rw-r--r--intern/cycles/render/background.h6
-rw-r--r--intern/cycles/render/bake.cpp8
-rw-r--r--intern/cycles/render/bake.h10
-rw-r--r--intern/cycles/render/buffers.cpp26
-rw-r--r--intern/cycles/render/buffers.h14
-rw-r--r--intern/cycles/render/camera.cpp24
-rw-r--r--intern/cycles/render/camera.h12
-rw-r--r--intern/cycles/render/constant_fold.cpp8
-rw-r--r--intern/cycles/render/constant_fold.h4
-rw-r--r--intern/cycles/render/curves.cpp20
-rw-r--r--intern/cycles/render/curves.h4
-rw-r--r--intern/cycles/render/film.cpp26
-rw-r--r--intern/cycles/render/film.h10
-rw-r--r--intern/cycles/render/graph.cpp48
-rw-r--r--intern/cycles/render/graph.h25
-rw-r--r--intern/cycles/render/image.cpp36
-rw-r--r--intern/cycles/render/image.h12
-rw-r--r--intern/cycles/render/integrator.cpp20
-rw-r--r--intern/cycles/render/integrator.h6
-rw-r--r--intern/cycles/render/light.cpp41
-rw-r--r--intern/cycles/render/light.h8
-rw-r--r--intern/cycles/render/mesh.cpp53
-rw-r--r--intern/cycles/render/mesh.h25
-rw-r--r--intern/cycles/render/mesh_displace.cpp18
-rw-r--r--intern/cycles/render/mesh_subdivision.cpp16
-rw-r--r--intern/cycles/render/nodes.cpp107
-rw-r--r--intern/cycles/render/nodes.h18
-rw-r--r--intern/cycles/render/object.cpp40
-rw-r--r--intern/cycles/render/object.h17
-rw-r--r--intern/cycles/render/osl.cpp32
-rw-r--r--intern/cycles/render/osl.h12
-rw-r--r--intern/cycles/render/particles.cpp18
-rw-r--r--intern/cycles/render/particles.h4
-rw-r--r--intern/cycles/render/scene.cpp42
-rw-r--r--intern/cycles/render/scene.h21
-rw-r--r--intern/cycles/render/session.cpp57
-rw-r--r--intern/cycles/render/session.h18
-rw-r--r--intern/cycles/render/shader.cpp32
-rw-r--r--intern/cycles/render/shader.h20
-rw-r--r--intern/cycles/render/sobol.cpp6
-rw-r--r--intern/cycles/render/sobol.h2
-rw-r--r--intern/cycles/render/svm.cpp30
-rw-r--r--intern/cycles/render/svm.h12
-rw-r--r--intern/cycles/render/tables.cpp10
-rw-r--r--intern/cycles/render/tables.h2
-rw-r--r--intern/cycles/render/tile.cpp8
-rw-r--r--intern/cycles/render/tile.h5
-rw-r--r--intern/cycles/subd/CMakeLists.txt7
-rw-r--r--intern/cycles/subd/subd_dice.cpp10
-rw-r--r--intern/cycles/subd/subd_dice.h4
-rw-r--r--intern/cycles/subd/subd_patch.cpp8
-rw-r--r--intern/cycles/subd/subd_patch.h4
-rw-r--r--intern/cycles/subd/subd_patch_table.cpp6
-rw-r--r--intern/cycles/subd/subd_patch_table.h4
-rw-r--r--intern/cycles/subd/subd_split.cpp16
-rw-r--r--intern/cycles/subd/subd_split.h6
-rw-r--r--intern/cycles/util/CMakeLists.txt3
-rw-r--r--intern/cycles/util/util_aligned_malloc.cpp4
-rw-r--r--intern/cycles/util/util_aligned_malloc.h2
-rw-r--r--intern/cycles/util/util_atomic.h28
-rw-r--r--intern/cycles/util/util_boundbox.h8
-rw-r--r--intern/cycles/util/util_color.h6
-rw-r--r--intern/cycles/util/util_debug.cpp30
-rw-r--r--intern/cycles/util/util_debug.h11
-rw-r--r--intern/cycles/util/util_guarded_allocator.cpp4
-rw-r--r--intern/cycles/util/util_guarded_allocator.h4
-rw-r--r--intern/cycles/util/util_half.h27
-rw-r--r--intern/cycles/util/util_hash.h2
-rw-r--r--intern/cycles/util/util_image.h4
-rw-r--r--intern/cycles/util/util_image_impl.h68
-rw-r--r--intern/cycles/util/util_logging.cpp13
-rw-r--r--intern/cycles/util/util_logging.h3
-rw-r--r--intern/cycles/util/util_math.h230
-rw-r--r--intern/cycles/util/util_math_cdf.cpp6
-rw-r--r--intern/cycles/util/util_math_cdf.h6
-rw-r--r--intern/cycles/util/util_math_intersect.h221
-rw-r--r--intern/cycles/util/util_md5.h4
-rw-r--r--intern/cycles/util/util_optimization.h2
-rw-r--r--intern/cycles/util/util_path.cpp21
-rw-r--r--intern/cycles/util/util_path.h8
-rw-r--r--intern/cycles/util/util_progress.h8
-rw-r--r--intern/cycles/util/util_simd.cpp2
-rw-r--r--intern/cycles/util/util_simd.h14
-rw-r--r--intern/cycles/util/util_sky_model.cpp4
-rw-r--r--intern/cycles/util/util_ssef.h8
-rw-r--r--intern/cycles/util/util_stack_allocator.h4
-rw-r--r--intern/cycles/util/util_static_assert.h4
-rw-r--r--intern/cycles/util/util_stats.h2
-rw-r--r--intern/cycles/util/util_string.cpp6
-rw-r--r--intern/cycles/util/util_string.h2
-rw-r--r--intern/cycles/util/util_system.cpp10
-rw-r--r--intern/cycles/util/util_system.h2
-rw-r--r--intern/cycles/util/util_task.cpp12
-rw-r--r--intern/cycles/util/util_task.h8
-rw-r--r--intern/cycles/util/util_thread.cpp6
-rw-r--r--intern/cycles/util/util_thread.h2
-rw-r--r--intern/cycles/util/util_time.cpp4
-rw-r--r--intern/cycles/util/util_transform.cpp6
-rw-r--r--intern/cycles/util/util_transform.h4
-rw-r--r--intern/cycles/util/util_types.h41
-rw-r--r--intern/cycles/util/util_vector.h6
-rw-r--r--intern/cycles/util/util_view.cpp10
-rw-r--r--intern/cycles/util/util_windows.cpp2
-rw-r--r--intern/decklink/CMakeLists.txt4
-rw-r--r--intern/ffmpeg/ffmpeg_compat.h7
-rw-r--r--intern/gawain/CMakeLists.txt34
-rw-r--r--intern/gawain/gawain/attrib_binding.h (renamed from source/blender/gpu/gawain/attrib_binding.h)0
-rw-r--r--intern/gawain/gawain/batch.h (renamed from source/blender/gpu/gawain/batch.h)10
-rw-r--r--intern/gawain/gawain/buffer_id.h (renamed from source/blender/gpu/gawain/buffer_id.h)0
-rw-r--r--intern/gawain/gawain/common.h (renamed from source/blender/gpu/gawain/common.h)26
-rw-r--r--intern/gawain/gawain/element.h (renamed from source/blender/gpu/gawain/element.h)2
-rw-r--r--intern/gawain/gawain/imm_util.h (renamed from source/blender/gpu/gawain/imm_util.h)0
-rw-r--r--intern/gawain/gawain/immediate.h (renamed from source/blender/gpu/gawain/immediate.h)4
-rw-r--r--intern/gawain/gawain/primitive.h44
-rw-r--r--intern/gawain/gawain/shader_interface.h49
-rw-r--r--intern/gawain/gawain/vertex_buffer.h (renamed from source/blender/gpu/gawain/vertex_buffer.h)0
-rw-r--r--intern/gawain/gawain/vertex_format.h (renamed from source/blender/gpu/gawain/vertex_format.h)2
-rw-r--r--intern/gawain/src/attrib_binding.c (renamed from source/blender/gpu/gawain/attrib_binding.c)0
-rw-r--r--intern/gawain/src/batch.c (renamed from source/blender/gpu/gawain/batch.c)131
-rw-r--r--intern/gawain/src/buffer_id.cpp (renamed from source/blender/gpu/gawain/buffer_id.cpp)0
-rw-r--r--intern/gawain/src/element.c (renamed from source/blender/gpu/gawain/element.c)0
-rw-r--r--intern/gawain/src/imm_util.c (renamed from source/blender/gpu/gawain/imm_util.c)0
-rw-r--r--intern/gawain/src/immediate.c (renamed from source/blender/gpu/gawain/immediate.c)24
-rw-r--r--intern/gawain/src/primitive.c41
-rw-r--r--intern/gawain/src/shader_interface.c140
-rw-r--r--intern/gawain/src/vertex_buffer.c (renamed from source/blender/gpu/gawain/vertex_buffer.c)0
-rw-r--r--intern/gawain/src/vertex_format.c (renamed from source/blender/gpu/gawain/vertex_format.c)6
-rw-r--r--intern/ghost/GHOST_C-api.h5
-rw-r--r--intern/ghost/GHOST_IWindow.h6
-rw-r--r--intern/ghost/GHOST_Types.h1
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp6
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp78
-rw-r--r--intern/ghost/intern/GHOST_Window.h9
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.cpp16
-rw-r--r--intern/ghost/intern/GHOST_WindowSDL.h2
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.cpp18
-rw-r--r--intern/ghost/intern/GHOST_WindowWin32.h11
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp45
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h2
-rw-r--r--intern/ghost/test/CMakeLists.txt3
-rw-r--r--intern/libmv/libmv/numeric/numeric.h2
-rw-r--r--intern/opencolorio/CMakeLists.txt1
-rw-r--r--intern/opencolorio/gpu_shader_display_transform.glsl15
-rw-r--r--intern/opencolorio/gpu_shader_display_transform_vertex.glsl18
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc30
-rw-r--r--make.bat27
-rw-r--r--release/darwin/blender.app/Contents/Info.plist2
-rw-r--r--release/datafiles/blender_icons.svg88
-rw-r--r--release/datafiles/blender_icons16/icon16_normalize_fcurves.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_normalize_fcurves.datbin0 -> 4120 bytes
-rw-r--r--release/scripts/freestyle/modules/freestyle/shaders.py4
-rw-r--r--release/scripts/freestyle/modules/parameter_editor.py12
-rw-r--r--release/scripts/modules/addon_utils.py16
-rw-r--r--release/scripts/modules/bl_app_override/__init__.py202
-rw-r--r--release/scripts/modules/bl_app_override/helpers.py167
-rw-r--r--release/scripts/modules/bl_app_template_utils.py198
-rw-r--r--release/scripts/modules/bpy/__init__.py10
-rw-r--r--release/scripts/modules/bpy/path.py4
-rw-r--r--release/scripts/modules/bpy/utils/__init__.py82
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py9
-rw-r--r--release/scripts/modules/bpy_types.py56
-rw-r--r--release/scripts/modules/rna_keymap_ui.py7
-rw-r--r--release/scripts/presets/interface_theme/back_to_black.xml119
-rw-r--r--release/scripts/presets/keyconfig/3dsmax.py14
-rw-r--r--release/scripts/presets/keyconfig/maya.py8
-rw-r--r--release/scripts/startup/bl_operators/__init__.py14
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py5
-rw-r--r--release/scripts/startup/bl_operators/anim.py42
-rw-r--r--release/scripts/startup/bl_operators/clip.py19
-rw-r--r--release/scripts/startup/bl_operators/console.py9
-rw-r--r--release/scripts/startup/bl_operators/file.py5
-rw-r--r--release/scripts/startup/bl_operators/freestyle.py18
-rw-r--r--release/scripts/startup/bl_operators/image.py8
-rw-r--r--release/scripts/startup/bl_operators/mask.py5
-rw-r--r--release/scripts/startup/bl_operators/mesh.py12
-rw-r--r--release/scripts/startup/bl_operators/node.py29
-rw-r--r--release/scripts/startup/bl_operators/object.py31
-rw-r--r--release/scripts/startup/bl_operators/object_align.py36
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py24
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py5
-rw-r--r--release/scripts/startup/bl_operators/presets.py25
-rw-r--r--release/scripts/startup/bl_operators/rigidbody.py13
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py5
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py7
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py5
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py5
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py11
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py5
-rw-r--r--release/scripts/startup/bl_operators/view3d.py8
-rw-r--r--release/scripts/startup/bl_operators/wm.py288
-rw-r--r--release/scripts/startup/bl_ui/__init__.py16
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_collection.py117
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py18
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py35
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py18
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py35
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py43
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py37
-rw-r--r--release/scripts/startup/bl_ui/properties_data_speaker.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py27
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py36
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py74
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py67
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py26
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py8
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py32
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py15
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py51
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py73
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py17
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py66
-rw-r--r--release/scripts/startup/bl_ui/space_collections.py41
-rw-r--r--release/scripts/startup/bl_ui/space_console.py12
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py18
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py15
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py24
-rw-r--r--release/scripts/startup/bl_ui/space_image.py56
-rw-r--r--release/scripts/startup/bl_ui/space_info.py34
-rw-r--r--release/scripts/startup/bl_ui/space_logic.py13
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py16
-rw-r--r--release/scripts/startup/bl_ui/space_node.py29
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py30
-rw-r--r--release/scripts/startup/bl_ui/space_properties.py18
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py76
-rw-r--r--release/scripts/startup/bl_ui/space_text.py40
-rw-r--r--release/scripts/startup/bl_ui/space_time.py21
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py121
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py246
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py66
-rw-r--r--release/scripts/startup/keyingsets_builtins.py32
-rw-r--r--release/scripts/startup/nodeitems_builtins.py6
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/alembic/intern/abc_archive.cc22
-rw-r--r--source/blender/alembic/intern/abc_curves.cc2
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc5
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc14
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc2
-rw-r--r--source/blender/alembic/intern/abc_points.cc2
-rw-r--r--source/blender/alembic/intern/abc_transform.cc4
-rw-r--r--source/blender/alembic/intern/abc_util.cc14
-rw-r--r--source/blender/alembic/intern/abc_util.h19
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc4
-rw-r--r--source/blender/blenfont/intern/blf.c8
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c11
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h3
-rw-r--r--source/blender/blenkernel/BKE_appdir.h4
-rw-r--r--source/blender/blenkernel/BKE_blender.h12
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h20
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h14
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h3
-rw-r--r--source/blender/blenkernel/BKE_cloth.h6
-rw-r--r--source/blender/blenkernel/BKE_collection.h23
-rw-r--r--source/blender/blenkernel/BKE_context.h3
-rw-r--r--source/blender/blenkernel/BKE_curve.h11
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h5
-rw-r--r--source/blender/blenkernel/BKE_layer.h124
-rw-r--r--source/blender/blenkernel/BKE_mesh.h6
-rw-r--r--source/blender/blenkernel/BKE_mesh_render.h9
-rw-r--r--source/blender/blenkernel/BKE_node.h2
-rw-r--r--source/blender/blenkernel/BKE_object.h21
-rw-r--r--source/blender/blenkernel/BKE_outliner_treehash.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h7
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/BKE_scene.h5
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c74
-rw-r--r--source/blender/blenkernel/intern/appdir.c178
-rw-r--r--source/blender/blenkernel/intern/blender.c120
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c6
-rw-r--r--source/blender/blenkernel/intern/blendfile.c90
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c327
-rw-r--r--source/blender/blenkernel/intern/camera.c4
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c39
-rw-r--r--source/blender/blenkernel/intern/cloth.c37
-rw-r--r--source/blender/blenkernel/intern/collection.c225
-rw-r--r--source/blender/blenkernel/intern/collision.c12
-rw-r--r--source/blender/blenkernel/intern/colortools.c2
-rw-r--r--source/blender/blenkernel/intern/context.c17
-rw-r--r--source/blender/blenkernel/intern/curve.c23
-rw-r--r--source/blender/blenkernel/intern/customdata.c55
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c12
-rw-r--r--source/blender/blenkernel/intern/displist.c2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c42
-rw-r--r--source/blender/blenkernel/intern/effect.c8
-rw-r--r--source/blender/blenkernel/intern/fcurve.c146
-rw-r--r--source/blender/blenkernel/intern/idprop.c15
-rw-r--r--source/blender/blenkernel/intern/image.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c2
-rw-r--r--source/blender/blenkernel/intern/layer.c1014
-rw-r--r--source/blender/blenkernel/intern/library.c2
-rw-r--r--source/blender/blenkernel/intern/library_query.c1
-rw-r--r--source/blender/blenkernel/intern/library_remap.c4
-rw-r--r--source/blender/blenkernel/intern/material.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.c405
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c380
-rw-r--r--source/blender/blenkernel/intern/mesh_render.c1202
-rw-r--r--source/blender/blenkernel/intern/object.c125
-rw-r--r--source/blender/blenkernel/intern/object_update.c13
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c39
-rw-r--r--source/blender/blenkernel/intern/paint.c30
-rw-r--r--source/blender/blenkernel/intern/pbvh.c26
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c60
-rw-r--r--source/blender/blenkernel/intern/sequencer.c7
-rw-r--r--source/blender/blenkernel/intern/sound.c2
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c31
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c13
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c7
-rw-r--r--source/blender/blenlib/BLI_iterator.h7
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h16
-rw-r--r--source/blender/blenlib/BLI_listbase.h1
-rw-r--r--source/blender/blenlib/BLI_math_color.h3
-rw-r--r--source/blender/blenlib/BLI_math_geom.h17
-rw-r--r--source/blender/blenlib/BLI_path_util.h27
-rw-r--r--source/blender/blenlib/BLI_rect.h2
-rw-r--r--source/blender/blenlib/BLI_task.h12
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c470
-rw-r--r--source/blender/blenlib/intern/array_store.c72
-rw-r--r--source/blender/blenlib/intern/listbase.c28
-rw-r--r--source/blender/blenlib/intern/math_geom.c229
-rw-r--r--source/blender/blenlib/intern/path_util.c173
-rw-r--r--source/blender/blenlib/intern/polyfill2d.c17
-rw-r--r--source/blender/blenlib/intern/rct.c16
-rw-r--r--source/blender/blenlib/intern/task.c332
-rw-r--r--source/blender/blenlib/intern/threads.c39
-rw-r--r--source/blender/blenloader/BLO_readfile.h20
-rw-r--r--source/blender/blenloader/CMakeLists.txt6
-rw-r--r--source/blender/blenloader/intern/readblenentry.c15
-rw-r--r--source/blender/blenloader/intern/readfile.c963
-rw-r--r--source/blender/blenloader/intern/readfile.h2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c34
-rw-r--r--source/blender/blenloader/intern/versioning_280.c83
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c12
-rw-r--r--source/blender/blenloader/intern/writefile.c2195
-rw-r--r--source/blender/bmesh/CMakeLists.txt2
-rw-r--r--source/blender/bmesh/bmesh.h5
-rw-r--r--source/blender/bmesh/bmesh_tools.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_core.c142
-rw-r--r--source/blender/bmesh/intern/bmesh_core.h52
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh.c149
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.c43
-rw-r--r--source/blender/bmesh/intern/bmesh_mods.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c2
-rw-r--r--source/blender/bmesh/operators/bmo_bisect_plane.c7
-rw-r--r--source/blender/bmesh/operators/bmo_dupe.c4
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c4
-rw-r--r--source/blender/bmesh/operators/bmo_offset_edgeloops.c4
-rw-r--r--source/blender/bmesh/operators/bmo_primitive.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.c39
-rw-r--r--source/blender/bmesh/tools/bmesh_bisect_plane.h2
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.c4
-rw-r--r--source/blender/bmesh/tools/bmesh_intersect.h2
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.c133
-rw-r--r--source/blender/bmesh/tools/bmesh_separate.h (renamed from source/blender/editors/space_collections/collections_intern.h)21
-rw-r--r--source/blender/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/collada/ArmatureExporter.cpp75
-rw-r--r--source/blender/collada/ArmatureExporter.h2
-rw-r--r--source/blender/collada/ArmatureImporter.cpp65
-rw-r--r--source/blender/collada/ControllerExporter.cpp120
-rw-r--r--source/blender/collada/ControllerExporter.h2
-rw-r--r--source/blender/collada/ExportSettings.h3
-rw-r--r--source/blender/collada/ImportSettings.h1
-rw-r--r--source/blender/collada/SkinInfo.cpp1
-rw-r--r--source/blender/collada/TransformReader.cpp23
-rw-r--r--source/blender/collada/TransformReader.h5
-rw-r--r--source/blender/collada/TransformWriter.cpp7
-rw-r--r--source/blender/collada/TransformWriter.h3
-rw-r--r--source/blender/collada/collada.cpp14
-rw-r--r--source/blender/collada/collada.h11
-rw-r--r--source/blender/collada/collada_internal.cpp19
-rw-r--r--source/blender/collada/collada_internal.h7
-rw-r--r--source/blender/collada/collada_utils.cpp224
-rw-r--r--source/blender/collada/collada_utils.h15
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp6
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp16
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.cpp2
-rw-r--r--source/blender/depsgraph/CMakeLists.txt2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc49
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc54
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h13
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc121
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc16
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc105
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_layer.cc134
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc22
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc20
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc23
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type_defines.cc4
-rw-r--r--source/blender/depsgraph/intern/depsgraph_types.h43
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc130
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc5
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.cc7
-rw-r--r--source/blender/depsgraph/intern/nodes/deg_node_component.h4
-rw-r--r--source/blender/draw/CMakeLists.txt61
-rw-r--r--source/blender/draw/DRW_engine.h34
-rw-r--r--source/blender/draw/engines/clay/clay.c626
-rw-r--r--source/blender/draw/engines/clay/clay.h11
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl14
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_vert.glsl8
-rw-r--r--source/blender/draw/engines/eevee/eevee.c255
-rw-r--r--source/blender/draw/engines/eevee/eevee.h31
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c162
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut.h2321
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h85
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl197
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl173
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl133
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl16
-rw-r--r--source/blender/draw/engines/eevee/shaders/ltc_lib.glsl243
-rw-r--r--source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl28
-rw-r--r--source/blender/draw/intern/DRW_render.h105
-rw-r--r--source/blender/draw/intern/draw_armature.c443
-rw-r--r--source/blender/draw/intern/draw_cache.c967
-rw-r--r--source/blender/draw/intern/draw_cache.h27
-rw-r--r--source/blender/draw/intern/draw_common.c326
-rw-r--r--source/blender/draw/intern/draw_common.h116
-rw-r--r--source/blender/draw/intern/draw_manager.c1121
-rw-r--r--source/blender/draw/intern/draw_mode_pass.c541
-rw-r--r--source/blender/draw/intern/draw_view.c707
-rw-r--r--source/blender/draw/intern/draw_view.h (renamed from source/blender/draw/intern/draw_mode_pass.h)28
-rw-r--r--source/blender/draw/modes/draw_mode_engines.h44
-rw-r--r--source/blender/draw/modes/edit_armature_mode.c139
-rw-r--r--source/blender/draw/modes/edit_curve_mode.c272
-rw-r--r--source/blender/draw/modes/edit_lattice_mode.c270
-rw-r--r--source/blender/draw/modes/edit_mesh_mode.c500
-rw-r--r--source/blender/draw/modes/edit_metaball_mode.c270
-rw-r--r--source/blender/draw/modes/edit_surface_mode.c270
-rw-r--r--source/blender/draw/modes/edit_text_mode.c270
-rw-r--r--source/blender/draw/modes/object_mode.c1061
-rw-r--r--source/blender/draw/modes/paint_texture_mode.c270
-rw-r--r--source/blender/draw/modes/paint_vertex_mode.c270
-rw-r--r--source/blender/draw/modes/paint_weight_mode.c267
-rw-r--r--source/blender/draw/modes/particle_mode.c265
-rw-r--r--source/blender/draw/modes/pose_mode.c265
-rw-r--r--source/blender/draw/modes/sculpt_mode.c264
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl55
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_face_vert.glsl18
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_geom.glsl15
-rw-r--r--source/blender/draw/modes/shaders/edit_normals_vert.glsl24
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl12
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_facedot_vert.glsl14
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl27
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl29
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_frag.glsl185
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_geom_edge.glsl143
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_geom_tri.glsl277
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_loosevert_vert.glsl48
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl24
-rw-r--r--source/blender/draw/modes/shaders/edit_overlay_vert.glsl23
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl147
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl66
-rw-r--r--source/blender/draw/modes/shaders/object_outline_detect_frag.glsl61
-rw-r--r--source/blender/draw/modes/shaders/object_outline_expand_frag.glsl45
-rw-r--r--source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl11
-rw-r--r--source/blender/editors/CMakeLists.txt1
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c5
-rw-r--r--source/blender/editors/animation/anim_draw.c101
-rw-r--r--source/blender/editors/animation/anim_filter.c61
-rw-r--r--source/blender/editors/animation/anim_markers.c43
-rw-r--r--source/blender/editors/animation/anim_ops.c31
-rw-r--r--source/blender/editors/animation/keyframes_draw.c16
-rw-r--r--source/blender/editors/armature/armature_intern.h6
-rw-r--r--source/blender/editors/armature/armature_naming.c2
-rw-r--r--source/blender/editors/armature/armature_select.c124
-rw-r--r--source/blender/editors/armature/editarmature_sketch.c185
-rw-r--r--source/blender/editors/armature/pose_select.c16
-rw-r--r--source/blender/editors/armature/pose_slide.c284
-rw-r--r--source/blender/editors/armature/reeb.c234
-rw-r--r--source/blender/editors/curve/editcurve.c99
-rw-r--r--source/blender/editors/curve/editcurve_paint.c61
-rw-r--r--source/blender/editors/gpencil/drawgpencil.c99
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c17
-rw-r--r--source/blender/editors/gpencil/gpencil_interpolate.c27
-rw-r--r--source/blender/editors/include/BIF_gl.h41
-rw-r--r--source/blender/editors/include/BIF_glutil.h164
-rw-r--r--source/blender/editors/include/ED_anim_api.h1
-rw-r--r--source/blender/editors/include/ED_armature.h12
-rw-r--r--source/blender/editors/include/ED_image.h3
-rw-r--r--source/blender/editors/include/ED_object.h1
-rw-r--r--source/blender/editors/include/ED_particle.h21
-rw-r--r--source/blender/editors/include/ED_screen.h1
-rw-r--r--source/blender/editors/include/ED_sculpt.h3
-rw-r--r--source/blender/editors/include/ED_space_api.h1
-rw-r--r--source/blender/editors/include/ED_uvedit.h4
-rw-r--r--source/blender/editors/include/ED_view3d.h38
-rw-r--r--source/blender/editors/include/UI_icons.h2
-rw-r--r--source/blender/editors/include/UI_interface.h9
-rw-r--r--source/blender/editors/include/UI_interface_icons.h2
-rw-r--r--source/blender/editors/interface/interface.c48
-rw-r--r--source/blender/editors/interface/interface_align.c6
-rw-r--r--source/blender/editors/interface/interface_anim.c2
-rw-r--r--source/blender/editors/interface/interface_draw.c254
-rw-r--r--source/blender/editors/interface/interface_eyedropper.c2
-rw-r--r--source/blender/editors/interface/interface_handlers.c82
-rw-r--r--source/blender/editors/interface/interface_icons.c65
-rw-r--r--source/blender/editors/interface/interface_intern.h8
-rw-r--r--source/blender/editors/interface/interface_layout.c117
-rw-r--r--source/blender/editors/interface/interface_ops.c109
-rw-r--r--source/blender/editors/interface/interface_panel.c221
-rw-r--r--source/blender/editors/interface/interface_regions.c30
-rw-r--r--source/blender/editors/interface/interface_templates.c61
-rw-r--r--source/blender/editors/interface/interface_utils.c10
-rw-r--r--source/blender/editors/interface/interface_widgets.c551
-rw-r--r--source/blender/editors/interface/resources.c38
-rw-r--r--source/blender/editors/interface/view2d.c11
-rw-r--r--source/blender/editors/io/io_alembic.c6
-rw-r--r--source/blender/editors/io/io_collada.c93
-rw-r--r--source/blender/editors/mask/mask_draw.c468
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c50
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c38
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c4
-rw-r--r--source/blender/editors/mesh/editmesh_rip.c4
-rw-r--r--source/blender/editors/metaball/mball_edit.c7
-rw-r--r--source/blender/editors/object/object_add.c33
-rw-r--r--source/blender/editors/object/object_bake.c6
-rw-r--r--source/blender/editors/object/object_bake_api.c19
-rw-r--r--source/blender/editors/object/object_edit.c55
-rw-r--r--source/blender/editors/object/object_hook.c11
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c60
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/editors/object/object_relations.c4
-rw-r--r--source/blender/editors/object/object_select.c8
-rw-r--r--source/blender/editors/object/object_vgroup.c24
-rw-r--r--source/blender/editors/physics/particle_edit.c218
-rw-r--r--source/blender/editors/physics/particle_object.c43
-rw-r--r--source/blender/editors/physics/physics_pointcache.c14
-rw-r--r--source/blender/editors/physics/rigidbody_constraint.c10
-rw-r--r--source/blender/editors/render/render_internal.c31
-rw-r--r--source/blender/editors/render/render_opengl.c50
-rw-r--r--source/blender/editors/render/render_preview.c28
-rw-r--r--source/blender/editors/render/render_shading.c4
-rw-r--r--source/blender/editors/render/render_update.c10
-rw-r--r--source/blender/editors/screen/area.c84
-rw-r--r--source/blender/editors/screen/glutil.c737
-rw-r--r--source/blender/editors/screen/screen_context.c5
-rw-r--r--source/blender/editors/screen/screen_draw.c218
-rw-r--r--source/blender/editors/screen/screen_ops.c57
-rw-r--r--source/blender/editors/screen/screendump.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c356
-rw-r--r--source/blender/editors/sculpt_paint/paint_hide.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c7
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c21
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_mask.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c61
-rw-r--r--source/blender/editors/sculpt_paint/paint_utils.c20
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c15
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_uv.c14
-rw-r--r--source/blender/editors/space_action/action_draw.c4
-rw-r--r--source/blender/editors/space_api/spacetypes.c1
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c26
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c4
-rw-r--r--source/blender/editors/space_clip/clip_draw.c821
-rw-r--r--source/blender/editors/space_clip/clip_graph_draw.c47
-rw-r--r--source/blender/editors/space_clip/clip_intern.h4
-rw-r--r--source/blender/editors/space_clip/clip_utils.c21
-rw-r--r--source/blender/editors/space_clip/space_clip.c14
-rw-r--r--source/blender/editors/space_clip/tracking_ops.c6
-rw-r--r--source/blender/editors/space_clip/tracking_ops_orient.c1
-rw-r--r--source/blender/editors/space_collections/CMakeLists.txt45
-rw-r--r--source/blender/editors/space_collections/collections_ops.c340
-rw-r--r--source/blender/editors/space_collections/space_collections.c182
-rw-r--r--source/blender/editors/space_console/console_draw.c4
-rw-r--r--source/blender/editors/space_file/file_draw.c36
-rw-r--r--source/blender/editors/space_file/fsmenu.c43
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c32
-rw-r--r--source/blender/editors/space_graph/graph_draw.c426
-rw-r--r--source/blender/editors/space_image/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_image/image_draw.c444
-rw-r--r--source/blender/editors/space_image/image_edit.c8
-rw-r--r--source/blender/editors/space_image/image_ops.c4
-rw-r--r--source/blender/editors/space_image/space_image.c8
-rw-r--r--source/blender/editors/space_info/textview.c7
-rw-r--r--source/blender/editors/space_nla/nla_draw.c8
-rw-r--r--source/blender/editors/space_node/drawnode.c340
-rw-r--r--source/blender/editors/space_node/node_add.c16
-rw-r--r--source/blender/editors/space_node/node_buttons.c11
-rw-r--r--source/blender/editors/space_node/node_draw.c136
-rw-r--r--source/blender/editors/space_node/node_edit.c11
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c458
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c554
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c157
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h95
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c286
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c67
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c120
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c299
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c234
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c13
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c3
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c706
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c23
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h2
-rw-r--r--source/blender/editors/space_text/text_draw.c251
-rw-r--r--source/blender/editors/space_time/space_time.c151
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c9
-rw-r--r--source/blender/editors/space_view3d/drawarmature.c1209
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c30
-rw-r--r--source/blender/editors/space_view3d/drawobject.c2455
-rw-r--r--source/blender/editors/space_view3d/drawsimdebug.c15
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c7
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c37
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c43
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c472
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c511
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c200
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h26
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c29
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c135
-rw-r--r--source/blender/editors/space_view3d/view3d_transform_manipulators.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c231
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c4
-rw-r--r--source/blender/editors/transform/transform.c24
-rw-r--r--source/blender/editors/transform/transform.h3
-rw-r--r--source/blender/editors/transform/transform_constraints.c9
-rw-r--r--source/blender/editors/transform/transform_conversions.c170
-rw-r--r--source/blender/editors/transform/transform_generics.c22
-rw-r--r--source/blender/editors/transform/transform_ops.c3
-rw-r--r--source/blender/editors/transform/transform_snap.c30
-rw-r--r--source/blender/editors/transform/transform_snap_object.c105
-rw-r--r--source/blender/editors/util/ed_util.c3
-rw-r--r--source/blender/editors/util/numinput.c2
-rw-r--r--source/blender/editors/util/undo.c16
-rw-r--r--source/blender/editors/uvedit/CMakeLists.txt1
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c196
-rw-r--r--source/blender/editors/uvedit/uvedit_smart_stitch.c135
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp9
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h15
-rw-r--r--source/blender/gpu/CMakeLists.txt56
-rw-r--r--source/blender/gpu/GPU_basic_shader.h3
-rw-r--r--source/blender/gpu/GPU_batch.h7
-rw-r--r--source/blender/gpu/GPU_buffers.h6
-rw-r--r--source/blender/gpu/GPU_debug.h3
-rw-r--r--source/blender/gpu/GPU_draw.h4
-rw-r--r--source/blender/gpu/GPU_framebuffer.h4
-rw-r--r--source/blender/gpu/GPU_immediate.h9
-rw-r--r--source/blender/gpu/GPU_lamp.h75
-rw-r--r--source/blender/gpu/GPU_material.h24
-rw-r--r--source/blender/gpu/GPU_matrix.h71
-rw-r--r--source/blender/gpu/GPU_select.h15
-rw-r--r--source/blender/gpu/GPU_shader.h31
-rw-r--r--source/blender/gpu/GPU_texture.h8
-rw-r--r--source/blender/gpu/GPU_viewport.h38
-rw-r--r--source/blender/gpu/intern/gpu_basic_shader.c160
-rw-r--r--source/blender/gpu/intern/gpu_batch.c71
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c97
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c6
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c176
-rw-r--r--source/blender/gpu/intern/gpu_debug.c440
-rw-r--r--source/blender/gpu/intern/gpu_draw.c68
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c151
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c475
-rw-r--r--source/blender/gpu/intern/gpu_lamp_private.h86
-rw-r--r--source/blender/gpu/intern/gpu_material.c443
-rw-r--r--source/blender/gpu/intern/gpu_matrix.c301
-rw-r--r--source/blender/gpu/intern/gpu_select.c277
-rw-r--r--source/blender/gpu/intern/gpu_select_pick.c740
-rw-r--r--source/blender/gpu/intern/gpu_select_private.h53
-rw-r--r--source/blender/gpu/intern/gpu_select_sample_query.c209
-rw-r--r--source/blender/gpu/intern/gpu_shader.c115
-rw-r--r--source/blender/gpu/intern/gpu_shader_private.h7
-rw-r--r--source/blender/gpu/intern/gpu_texture.c61
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c210
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl1
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl (renamed from source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_frag.glsl6
-rw-r--r--source/blender/gpu/shaders/gpu_shader_basic_vert.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl24
-rw-r--r--source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fire_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl56
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl65
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_lib.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl7
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl22
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl57
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl64
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl29
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl51
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl (renamed from source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl)0
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl25
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl16
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl17
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl12
-rw-r--r--source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl20
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl11
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl11
-rw-r--r--source/blender/imbuf/intern/imbuf.h2
-rw-r--r--source/blender/makesdna/DNA_ID.h9
-rw-r--r--source/blender/makesdna/DNA_action_types.h2
-rw-r--r--source/blender/makesdna/DNA_camera_types.h7
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h4
-rw-r--r--source/blender/makesdna/DNA_layer_types.h52
-rw-r--r--source/blender/makesdna/DNA_material_types.h30
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h42
-rw-r--r--source/blender/makesdna/DNA_node_types.h3
-rw-r--r--source/blender/makesdna/DNA_object_force.h1
-rw-r--r--source/blender/makesdna/DNA_object_types.h5
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h6
-rw-r--r--source/blender/makesdna/DNA_scene_types.h82
-rw-r--r--source/blender/makesdna/DNA_space_types.h22
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h21
-rw-r--r--source/blender/makesdna/DNA_world_types.h1
-rw-r--r--source/blender/makesrna/RNA_access.h5
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_action.c3
-rw-r--r--source/blender/makesrna/intern/rna_animation.c3
-rw-r--r--source/blender/makesrna/intern/rna_armature.c3
-rw-r--r--source/blender/makesrna/intern/rna_brush.c31
-rw-r--r--source/blender/makesrna/intern/rna_define.c3
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c3
-rw-r--r--source/blender/makesrna/intern/rna_image_api.c3
-rw-r--r--source/blender/makesrna/intern/rna_internal.h2
-rw-r--r--source/blender/makesrna/intern/rna_material.c143
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c9
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c51
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c7
-rw-r--r--source/blender/makesrna/intern/rna_object.c6
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c19
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c7
-rw-r--r--source/blender/makesrna/intern/rna_pose.c14
-rw-r--r--source/blender/makesrna/intern/rna_render.c9
-rw-r--r--source/blender/makesrna/intern/rna_scene.c760
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c122
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c45
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c4
-rw-r--r--source/blender/makesrna/intern/rna_space.c24
-rw-r--r--source/blender/makesrna/intern/rna_texture.c18
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c9
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c73
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c11
-rw-r--r--source/blender/modifiers/CMakeLists.txt1
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h1
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c1
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c2
-rw-r--r--source/blender/modifiers/intern/MOD_dynamicpaint.c2
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim.c7
-rw-r--r--source/blender/modifiers/intern/MOD_mirror.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c1
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c1210
-rw-r--r--source/blender/modifiers/intern/MOD_util.c1
-rw-r--r--source/blender/modifiers/intern/MOD_uvwarp.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_glare.c3
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c3
-rw-r--r--source/blender/nodes/shader/node_shader_util.h1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_fresnel.c5
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_layer_weight.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_brick.c2
-rw-r--r--source/blender/nodes/texture/node_texture_tree.c3
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp51
-rw-r--r--source/blender/physics/intern/implicit.h10
-rw-r--r--source/blender/physics/intern/implicit_blender.c34
-rw-r--r--source/blender/python/BPY_extern.h3
-rw-r--r--source/blender/python/generic/bgl.c413
-rw-r--r--source/blender/python/generic/py_capi_utils.c51
-rw-r--r--source/blender/python/generic/py_capi_utils.h7
-rw-r--r--source/blender/python/intern/bpy_interface.c46
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c1
-rw-r--r--source/blender/python/intern/bpy_utils_units.c2
-rw-r--r--source/blender/python/intern/gpu_offscreen.c14
-rw-r--r--source/blender/python/mathutils/mathutils_Matrix.c20
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_engine.h6
-rw-r--r--source/blender/render/intern/source/convertblender.c17
-rw-r--r--source/blender/render/intern/source/envmap.c16
-rw-r--r--source/blender/render/intern/source/external_engine.c9
-rw-r--r--source/blender/render/intern/source/pipeline.c6
-rw-r--r--source/blender/render/intern/source/pointdensity.c9
-rw-r--r--source/blender/render/intern/source/render_texture.c61
-rw-r--r--source/blender/render/intern/source/shadeoutput.c4
-rw-r--r--source/blender/render/intern/source/volume_precache.c10
-rw-r--r--source/blender/windowmanager/CMakeLists.txt4
-rw-r--r--source/blender/windowmanager/WM_api.h7
-rw-r--r--source/blender/windowmanager/WM_types.h9
-rw-r--r--source/blender/windowmanager/intern/wm.c34
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c8
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c20
-rw-r--r--source/blender/windowmanager/intern/wm_files.c330
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c328
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c10
-rw-r--r--source/blender/windowmanager/intern/wm_keymap.c11
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c162
-rw-r--r--source/blender/windowmanager/intern/wm_playanim.c23
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c28
-rw-r--r--source/blender/windowmanager/intern/wm_subwindow.c29
-rw-r--r--source/blender/windowmanager/intern/wm_window.c169
-rw-r--r--source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c7
-rw-r--r--source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c6
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h12
-rw-r--r--source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c13
-rw-r--r--source/blender/windowmanager/wm.h1
-rw-r--r--source/blender/windowmanager/wm_files.h5
-rw-r--r--source/blender/windowmanager/wm_window.h11
-rw-r--r--source/blenderplayer/CMakeLists.txt1
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c25
-rw-r--r--source/creator/creator_args.c20
-rw-r--r--source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp4
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp6
-rw-r--r--source/gameengine/GamePlayer/ghost/GPG_ghost.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp49
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp10
-rw-r--r--source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp1
-rw-r--r--source/gameengine/VideoTexture/FilterColor.cpp2
-rw-r--r--source/gameengine/VideoTexture/FilterColor.h4
-rw-r--r--tests/gtests/blenlib/BLI_array_store_test.cc28
-rw-r--r--tests/gtests/blenlib/BLI_path_util_test.cc237
-rw-r--r--tests/python/CMakeLists.txt24
-rw-r--r--tests/python/batch_import.py35
-rw-r--r--tests/python/bl_mesh_modifiers.py75
-rw-r--r--tests/python/bl_pyapi_idprop.py144
-rw-r--r--tests/python/bl_render_layer.py1040
-rw-r--r--tests/python/bl_run_operators.py12
-rwxr-xr-xtests/python/cycles_render_tests.py47
-rw-r--r--tests/python/render_layer/CMakeLists.txt159
-rw-r--r--tests/python/render_layer/render_layer_common.py721
-rw-r--r--tests/python/render_layer/test_active_collection.py76
-rw-r--r--tests/python/render_layer/test_collection_rename.py82
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_a.py58
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_b.py60
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_c.py58
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_d.py61
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_e.py60
-rw-r--r--tests/python/render_layer/test_evaluation_selectability_f.py48
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_a.py58
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_b.py58
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_c.py58
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_d.py55
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_e.py58
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_f.py59
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_g.py36
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_h.py36
-rw-r--r--tests/python/render_layer/test_evaluation_visibility_i.py36
-rw-r--r--tests/python/render_layer/test_layer_linking.py115
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_a.py54
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_b.py54
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_c.py54
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_d.py54
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_e.py46
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_f.py106
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_g.py87
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_h.py72
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_i.py79
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_j.py69
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_k.py46
-rw-r--r--tests/python/render_layer/test_move_above_below_layer_collection_l.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_a.py86
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_b.py75
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_c.py57
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_d.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_e.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_f.py57
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_g.py50
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_h.py90
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_i.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_a.py86
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_b.py75
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_c.py57
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_d.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_e.py66
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_f.py57
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_g.py50
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_h.py90
-rw-r--r--tests/python/render_layer/test_move_above_below_scene_collection_sync_i.py66
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_a.py75
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_b.py46
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_c.py46
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_d.py46
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_e.py46
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_f.py92
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_g.py83
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_h.py82
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_i.py46
-rw-r--r--tests/python/render_layer/test_move_into_layer_collection_j.py47
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_a.py59
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_b.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_c.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_d.py43
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_e.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_f.py57
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_g.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_h.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_i.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_j.py49
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_k.py42
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_l.py42
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_a.py43
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_b.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_c.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_d.py43
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_e.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_f.py57
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_g.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_h.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_i.py58
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_j.py49
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_k.py42
-rw-r--r--tests/python/render_layer/test_move_into_scene_collection_sync_l.py42
-rw-r--r--tests/python/render_layer/test_object_add_cylinder.py40
-rw-r--r--tests/python/render_layer/test_object_add_empty.py40
-rw-r--r--tests/python/render_layer/test_object_add_no_collection_cylinder.py38
-rw-r--r--tests/python/render_layer/test_object_add_no_collection_empty.py37
-rw-r--r--tests/python/render_layer/test_object_add_no_collection_torus.py37
-rw-r--r--tests/python/render_layer/test_object_add_torus.py40
-rw-r--r--tests/python/render_layer/test_object_copy.py99
-rw-r--r--tests/python/render_layer/test_object_delete_a.py37
-rw-r--r--tests/python/render_layer/test_object_delete_b.py37
-rw-r--r--tests/python/render_layer/test_object_link_a.py38
-rw-r--r--tests/python/render_layer/test_object_link_b.py39
-rw-r--r--tests/python/render_layer/test_object_link_c.py41
-rw-r--r--tests/python/render_layer/test_operator_context.py134
-rw-r--r--tests/python/render_layer/test_scene_copy_a.py43
-rw-r--r--tests/python/render_layer/test_scene_copy_b.py44
-rw-r--r--tests/python/render_layer/test_scene_copy_c.py43
-rw-r--r--tests/python/render_layer/test_scene_copy_d.py43
-rw-r--r--tests/python/render_layer/test_scene_write_read.py150
-rw-r--r--tests/python/render_layer/test_syncing.py119
1213 files changed, 58737 insertions, 27647 deletions
diff --git a/.gitmodules b/.gitmodules
index 0b8228e3f14..11ce247b455 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,16 +1,24 @@
[submodule "release/scripts/addons"]
path = release/scripts/addons
url = ../blender-addons.git
+ branch = blender2.8
ignore = all
+ branch = master
[submodule "release/scripts/addons_contrib"]
path = release/scripts/addons_contrib
url = ../blender-addons-contrib.git
+ branch = master
ignore = all
+ branch = master
[submodule "release/datafiles/locale"]
path = release/datafiles/locale
url = ../blender-translations.git
+ branch = master
ignore = all
+ branch = master
[submodule "source/tools"]
path = source/tools
url = ../blender-dev-tools.git
+ branch = master
ignore = all
+ branch = master
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a107dd78fbb..4fe6df2c67b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -447,6 +447,7 @@ option(WITH_BOOST "Enable features depending on boost" ON)
# Unit testsing
option(WITH_GTESTS "Enable GTest unit testing" OFF)
+option(WITH_OPENGL_TESTS "Enable OpenGL related unit testing (Experimental)" OFF)
# Documentation
@@ -473,12 +474,6 @@ mark_as_advanced(
WITH_GL_PROFILE_ES20
)
-if(WITH_GL_PROFILE_COMPAT)
- set(WITH_GLU ON)
-else()
- set(WITH_GLU OFF)
-endif()
-
if(WIN32)
option(WITH_GL_ANGLE "Link with the ANGLE library, an OpenGL ES 2.0 implementation based on Direct3D, instead of the system OpenGL library." OFF)
mark_as_advanced(WITH_GL_ANGLE)
@@ -519,18 +514,20 @@ endif()
option(WITH_LEGACY_DEPSGRAPH "Build Blender with legacy dependency graph" ON)
mark_as_advanced(WITH_LEGACY_DEPSGRAPH)
-# Use hardcoded paths or find_package to find externals
-option(WITH_WINDOWS_FIND_MODULES "Use find_package to locate libraries" OFF)
-mark_as_advanced(WITH_WINDOWS_FIND_MODULES)
+if(WIN32)
+ # Use hardcoded paths or find_package to find externals
+ option(WITH_WINDOWS_FIND_MODULES "Use find_package to locate libraries" OFF)
+ mark_as_advanced(WITH_WINDOWS_FIND_MODULES)
-option(WITH_WINDOWS_CODESIGN "Use signtool to sign the final binary." OFF)
-mark_as_advanced(WITH_WINDOWS_CODESIGN)
+ option(WITH_WINDOWS_CODESIGN "Use signtool to sign the final binary." OFF)
+ mark_as_advanced(WITH_WINDOWS_CODESIGN)
-set(WINDOWS_CODESIGN_PFX CACHE FILEPATH "Path to pfx file to use for codesigning.")
-mark_as_advanced(WINDOWS_CODESIGN_PFX)
+ set(WINDOWS_CODESIGN_PFX CACHE FILEPATH "Path to pfx file to use for codesigning.")
+ mark_as_advanced(WINDOWS_CODESIGN_PFX)
-set(WINDOWS_CODESIGN_PFX_PASSWORD CACHE STRING "password for pfx file used for codesigning.")
-mark_as_advanced(WINDOWS_CODESIGN_PFX_PASSWORD)
+ set(WINDOWS_CODESIGN_PFX_PASSWORD CACHE STRING "password for pfx file used for codesigning.")
+ mark_as_advanced(WINDOWS_CODESIGN_PFX_PASSWORD)
+endif()
# avoid using again
option_defaults_clear()
@@ -925,7 +922,7 @@ if(WITH_X11)
if(WITH_X11_ALPHA)
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
mark_as_advanced(X11_Xrender_LIB)
- if (X11_Xrender_LIB)
+ if(X11_Xrender_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xrender_LIB})
else()
set(WITH_X11_ALPHA OFF)
@@ -1055,11 +1052,6 @@ endif()
find_package(OpenGL)
blender_include_dirs_sys("${OPENGL_INCLUDE_DIR}")
-if(WITH_GLU)
- list(APPEND BLENDER_GL_LIBRARIES "${OPENGL_glu_LIBRARY}")
- list(APPEND GL_DEFINITIONS -DWITH_GLU)
-endif()
-
if(WITH_SYSTEM_GLES)
find_package_wrapper(OpenGLES)
endif()
@@ -1287,9 +1279,7 @@ else()
endif()
-if(NOT WITH_GLU)
- list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
-endif()
+list(APPEND GL_DEFINITIONS -DGLEW_NO_GLU)
#-----------------------------------------------------------------------------
# Configure Bullet
@@ -1797,7 +1787,6 @@ if(FIRST_RUN)
info_cfg_text("OpenGL:")
info_cfg_option(WITH_GLEW_ES)
- info_cfg_option(WITH_GLU)
info_cfg_option(WITH_GL_EGL)
info_cfg_option(WITH_GL_PROFILE_COMPAT)
info_cfg_option(WITH_GL_PROFILE_CORE)
diff --git a/GNUmakefile b/GNUmakefile
index 1fda1a25a92..7ee011911f8 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -1,4 +1,4 @@
-# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
+# -*- mode: gnumakefile; tab-width: 4; indent-tabs-mode: t; -*-
# vim: tabstop=4
#
# ##### BEGIN GPL LICENSE BLOCK #####
@@ -113,7 +113,7 @@ CMAKE_CONFIG = cmake $(BUILD_CMAKE_ARGS) \
# X11 spesific
ifdef DISPLAY
CMAKE_CONFIG_TOOL = cmake-gui
-else
+else
CMAKE_CONFIG_TOOL = ccmake
endif
@@ -127,7 +127,7 @@ all: .FORCE
# # if test ! -f $(BUILD_DIR)/CMakeCache.txt ; then \
# # $(CMAKE_CONFIG); \
# # fi
-
+
# # do this always incase of failed initial build, could be smarter here...
@$(CMAKE_CONFIG)
@@ -402,7 +402,7 @@ update: .FORCE
svn update ../lib/* ; \
fi
git pull --rebase
- git submodule foreach git pull --rebase origin master
+ git submodule update --remote
# -----------------------------------------------------------------------------
diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh
index c167d392100..5fc059c5c15 100755
--- a/build_files/build_environment/install_deps.sh
+++ b/build_files/build_environment/install_deps.sh
@@ -355,7 +355,7 @@ OPENVDB_FORCE_REBUILD=false
OPENVDB_SKIP=false
# Alembic needs to be compiled for now
-ALEMBIC_VERSION="1.6.0"
+ALEMBIC_VERSION="1.7.1"
ALEMBIC_VERSION_MIN=$ALEMBIC_VERSION
ALEMBIC_FORCE_BUILD=false
ALEMBIC_FORCE_REBUILD=false
@@ -2228,9 +2228,6 @@ compile_ALEMBIC() {
return
fi
- compile_HDF5
- PRINT ""
-
# To be changed each time we make edits that would modify the compiled result!
alembic_magic=2
_init_alembic
@@ -2258,6 +2255,12 @@ compile_ALEMBIC() {
cmake_d="-D CMAKE_INSTALL_PREFIX=$_inst"
+ # Without Boost or TR1, Alembic requires C++11.
+ if [ "$USE_CXX11" != true ]; then
+ cmake_d="$cmake_d -D ALEMBIC_LIB_USES_BOOST=ON"
+ cmake_d="$cmake_d -D ALEMBIC_LIB_USES_TR1=OFF"
+ fi
+
if [ -d $INST/boost ]; then
cmake_d="$cmake_d -D BOOST_ROOT=$INST/boost"
cmake_d="$cmake_d -D USE_STATIC_BOOST=ON"
@@ -2277,8 +2280,6 @@ compile_ALEMBIC() {
cmake_d="$cmake_d -D USE_STATIC_HDF5=OFF"
cmake_d="$cmake_d -D ALEMBIC_ILMBASE_LINK_STATIC=OFF"
cmake_d="$cmake_d -D ALEMBIC_SHARED_LIBS=OFF"
- cmake_d="$cmake_d -D ALEMBIC_LIB_USES_BOOST=ON"
- cmake_d="$cmake_d -D ALEMBIC_LIB_USES_TR1=OFF"
INFO "ILMBASE_ROOT=$INST/openexr"
fi
@@ -4244,7 +4245,7 @@ print_info() {
PRINT " $_3"
_buildargs="$_buildargs $_1 $_2 $_3"
if [ -d $INST/osl ]; then
- _1="-D CYCLES_OSL=$INST/osl"
+ _1="-D OSL_ROOT_DIR=$INST/osl"
PRINT " $_1"
_buildargs="$_buildargs $_1"
fi
diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg
index 387e53593b3..c650cb8c302 100644
--- a/build_files/buildbot/master.cfg
+++ b/build_files/buildbot/master.cfg
@@ -4,10 +4,10 @@
# <pep8 compliant>
# List of the branches being built automatically overnight
-NIGHT_SCHEDULE_BRANCHES = [None]
+NIGHT_SCHEDULE_BRANCHES = [None, "blender2.8"]
# List of the branches available for force build
-FORCE_SCHEDULE_BRANCHES = ["master", "gooseberry", "experimental-build"]
+FORCE_SCHEDULE_BRANCHES = ["master", "blender2.8", "experimental-build"]
"""
Stock Twisted directory lister doesn't provide any information about last file
@@ -127,7 +127,14 @@ def schedule_force_build(name):
project=forcesched.FixedParameter(name="project", default="", hide=True)),
# For now, hide other codebases.
forcesched.CodebaseParameter(hide=True, codebase="blender-translations"),
- forcesched.CodebaseParameter(hide=True, codebase="blender-addons"),
+ forcesched.CodebaseParameter(
+ codebase="blender-addons",
+ branch=forcesched.ChoiceStringParameter(
+ name="branch", choices=["master", "blender2.8"], default="master"),
+ repository=forcesched.FixedParameter(name="repository", default="", hide=True),
+ project=forcesched.FixedParameter(name="project", default="", hide=True),
+ revision=forcesched.FixedParameter(name="revision", default="", hide=True),
+ ),
forcesched.CodebaseParameter(hide=True, codebase="blender-addons-contrib"),
forcesched.CodebaseParameter(hide=True, codebase="blender-dev-tools"),
forcesched.CodebaseParameter(hide=True, codebase="lib svn")],
@@ -139,11 +146,15 @@ def schedule_build(name, hour, minute=0):
scheduler_name = "nightly " + name
if current_branch:
scheduler_name += ' ' + current_branch
+ # Use special addons submodule branch when building blender2.8 branch.
+ addons_branch = "master"
+ if current_branch == "blender2.8":
+ addons_branch = "blender2.8"
c['schedulers'].append(timed.Nightly(name=scheduler_name,
codebases={
"blender": {"repository": ""},
"blender-translations": {"repository": "", "branch": "master"},
- "blender-addons": {"repository": "", "branch": "master"},
+ "blender-addons": {"repository": "", "branch": addons_branch},
"blender-addons-contrib": {"repository": "", "branch": "master"},
"blender-dev-tools": {"repository": "", "branch": "master"},
"lib svn": {"repository": "", "branch": "trunk"}},
@@ -225,8 +236,7 @@ def git_step(branch=''):
def git_submodules_update():
- command = ['git', 'submodule', 'foreach', '--recursive',
- 'git', 'pull', 'origin', 'master']
+ command = ['git', 'submodule', 'update', '--remote']
return ShellCommand(name='Submodules Update',
command=command,
description='updating',
@@ -235,7 +245,10 @@ def git_submodules_update():
def lib_svn_step(dir):
- return SVN(name='lib svn',
+ name = "lib svn"
+ if dir == "darwin":
+ name = "C++11 lib svn"
+ return SVN(name=name,
baseURL='https://svn.blender.org/svnroot/bf-blender/%%BRANCH%%/lib/' + dir,
codebase='lib svn',
mode='update',
@@ -264,6 +277,9 @@ def generic_builder(id, libdir='', branch='', rsync=False):
f = BuildFactory()
if libdir != '':
f.addStep(lib_svn_step(libdir))
+ # Special trick to make sure we always have all the libs.
+ if libdir.startswith("darwin"):
+ f.addStep(lib_svn_step("darwin"))
for submodule in ('blender-translations',
'blender-addons',
@@ -286,7 +302,7 @@ def generic_builder(id, libdir='', branch='', rsync=False):
f.addStep(FileUpload(name='upload',
slavesrc='buildbot_upload.zip',
masterdest=filename,
- maxsize=150 * 1024 * 1024,
+ maxsize=180 * 1024 * 1024,
workdir='install'))
f.addStep(MasterShellCommand(name='unpack',
command=['python2.7', unpack_script, filename],
diff --git a/build_files/buildbot/master_unpack.py b/build_files/buildbot/master_unpack.py
index ec44705931c..67b628f668a 100644
--- a/build_files/buildbot/master_unpack.py
+++ b/build_files/buildbot/master_unpack.py
@@ -67,6 +67,9 @@ def get_platform(filename):
def get_branch(filename):
+ if filename.startswith("blender-2.8"):
+ return "blender2.8"
+
tokens = filename.split("-")
branch = ""
diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py
index 860dd1174cf..c8d69c38644 100644
--- a/build_files/buildbot/slave_compile.py
+++ b/build_files/buildbot/slave_compile.py
@@ -91,7 +91,6 @@ if 'cmake' in builder:
elif builder.startswith('win32'):
bits = 32
cmake_options.extend(['-G', 'Visual Studio 12 2013'])
- cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE:FILEPATH=C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/nvcc.exe')
elif builder.startswith('linux'):
tokens = builder.split("_")
@@ -111,8 +110,6 @@ if 'cmake' in builder:
cuda_chroot_name = 'buildbot_' + deb_name + '_x86_64'
targets = ['player', 'blender', 'cuda']
- cmake_extra_options.append('-DCUDA_NVCC_EXECUTABLE=/usr/local/cuda-8.0/bin/nvcc')
-
cmake_options.append("-C" + os.path.join(blender_dir, cmake_config_file))
# Prepare CMake options needed to configure cuda binaries compilation.
diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py
index 490f0456045..6929be85003 100644
--- a/build_files/buildbot/slave_pack.py
+++ b/build_files/buildbot/slave_pack.py
@@ -111,7 +111,8 @@ if builder.find('cmake') != -1:
if builder.endswith('vc2015'):
platform += "-vc14"
builderified_name = 'blender-{}-{}-{}'.format(blender_full_version, git_hash, platform)
- if branch != '':
+ # NOTE: Blender 2.8 is already respected by blender_full_version.
+ if branch != '' and branch != 'blender2.8':
builderified_name = branch + "-" + builderified_name
os.rename(result_file, "{}.zip".format(builderified_name))
@@ -177,7 +178,8 @@ if builder.find('cmake') != -1:
blender_hash,
blender_glibc,
blender_arch)
- if branch != '':
+ # NOTE: Blender 2.8 is already respected by blender_full_version.
+ if branch != '' and branch != 'blender2.8':
package_name = branch + "-" + package_name
upload_filename = package_name + ".tar.bz2"
diff --git a/build_files/cmake/buildinfo.cmake b/build_files/cmake/buildinfo.cmake
index 1f0a283ba0e..a43b99f5d1e 100644
--- a/build_files/cmake/buildinfo.cmake
+++ b/build_files/cmake/buildinfo.cmake
@@ -56,7 +56,7 @@ if(EXISTS ${SOURCE_DIR}/.git)
string(REGEX REPLACE "[\r\n]+" ";" _git_contains_branches "${_git_contains_branches}")
string(REGEX REPLACE ";[ \t]+" ";" _git_contains_branches "${_git_contains_branches}")
foreach(_branch ${_git_contains_branches})
- if (NOT "${_branch}" MATCHES "\\(HEAD.*")
+ if(NOT "${_branch}" MATCHES "\\(HEAD.*")
set(MY_WC_BRANCH "${_branch}")
break()
endif()
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index fa9c2a28cb5..7b47578cbc7 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -566,7 +566,6 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_editor_space_userpref
bf_editor_space_view3d
bf_editor_space_clip
- bf_editor_space_collections
bf_editor_transform
bf_editor_util
@@ -599,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_bmesh
bf_gpu
bf_draw
+ bf_intern_gawain
bf_blenloader
bf_blenkernel
bf_physics
@@ -1576,24 +1576,24 @@ macro(openmp_delayload
endmacro()
MACRO(WINDOWS_SIGN_TARGET target)
- if (WITH_WINDOWS_CODESIGN)
- if (!SIGNTOOL_EXE)
+ if(WITH_WINDOWS_CODESIGN)
+ if(!SIGNTOOL_EXE)
error("Codesigning is enabled, but signtool is not found")
else()
- if (WINDOWS_CODESIGN_PFX_PASSWORD)
+ if(WINDOWS_CODESIGN_PFX_PASSWORD)
set(CODESIGNPASSWORD /p ${WINDOWS_CODESIGN_PFX_PASSWORD})
else()
- if ($ENV{PFXPASSWORD})
+ if($ENV{PFXPASSWORD})
set(CODESIGNPASSWORD /p $ENV{PFXPASSWORD})
else()
- message( FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.")
+ message(FATAL_ERROR "WITH_WINDOWS_CODESIGN is on but WINDOWS_CODESIGN_PFX_PASSWORD not set, and environment variable PFXPASSWORD not found, unable to sign code.")
endif()
endif()
add_custom_command(TARGET ${target}
- POST_BUILD
- COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}>
- VERBATIM
- )
+ POST_BUILD
+ COMMAND ${SIGNTOOL_EXE} sign /f ${WINDOWS_CODESIGN_PFX} ${CODESIGNPASSWORD} $<TARGET_FILE:${target}>
+ VERBATIM
+ )
endif()
endif()
ENDMACRO()
diff --git a/build_files/cmake/packaging.cmake b/build_files/cmake/packaging.cmake
index c7063ed6772..5b894d96f95 100644
--- a/build_files/cmake/packaging.cmake
+++ b/build_files/cmake/packaging.cmake
@@ -1,5 +1,7 @@
-set(PROJECT_DESCRIPTION "Blender is a very fast and versatile 3D modeller/renderer.")
-set(PROJECT_COPYRIGHT "Copyright (C) 2001-2012 Blender Foundation")
+string(TIMESTAMP CURRENT_YEAR "%Y")
+
+set(PROJECT_DESCRIPTION "Blender is the free and open source 3D creation suite software.")
+set(PROJECT_COPYRIGHT "Copyright (C) 2001-${CURRENT_YEAR} Blender Foundation")
set(PROJECT_CONTACT "foundation@blender.org")
set(PROJECT_VENDOR "Blender Foundation")
@@ -38,8 +40,8 @@ unset(MY_WC_HASH)
# Force Package Name
execute_process(COMMAND date "+%Y%m%d" OUTPUT_VARIABLE CPACK_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
-if (MSVC)
- if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+if(MSVC)
+ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(PACKAGE_ARCH windows64)
else()
set(PACKAGE_ARCH windows32)
@@ -48,7 +50,7 @@ else(MSVC)
set(PACKAGE_ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
-if (CPACK_OVERRIDE_PACKAGENAME)
+if(CPACK_OVERRIDE_PACKAGENAME)
set(CPACK_PACKAGE_FILE_NAME ${CPACK_OVERRIDE_PACKAGENAME}-${PACKAGE_ARCH})
else()
set(CPACK_PACKAGE_FILE_NAME ${PROJECT_NAME_LOWER}-${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-git${CPACK_DATE}.${BUILD_REV}-${PACKAGE_ARCH})
@@ -135,4 +137,3 @@ unset(MINOR_VERSION)
unset(PATCH_VERSION)
unset(BUILD_REV)
-
diff --git a/build_files/cmake/platform/platform_apple.cmake b/build_files/cmake/platform/platform_apple.cmake
index 04485e31d98..f2a6aee7a59 100644
--- a/build_files/cmake/platform/platform_apple.cmake
+++ b/build_files/cmake/platform/platform_apple.cmake
@@ -23,6 +23,8 @@
# Libraries configuration for Apple.
+set(MACOSX_DEPLOYMENT_TARGET "10.9")
+
if(NOT DEFINED LIBDIR)
if(WITH_CXX11)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
diff --git a/build_files/cmake/platform/platform_win32_msvc.cmake b/build_files/cmake/platform/platform_win32_msvc.cmake
index 45a44596e61..3ea93a96290 100644
--- a/build_files/cmake/platform/platform_win32_msvc.cmake
+++ b/build_files/cmake/platform/platform_win32_msvc.cmake
@@ -33,7 +33,7 @@ endmacro()
macro(windows_find_package package_name
)
if(WITH_WINDOWS_FIND_MODULES)
- find_package( ${package_name})
+ find_package(${package_name})
endif(WITH_WINDOWS_FIND_MODULES)
endmacro()
diff --git a/doc/python_api/examples/gpu.offscreen.1.py b/doc/python_api/examples/gpu.offscreen.1.py
index 75ddf804e70..ff1a7ad7cce 100644
--- a/doc/python_api/examples/gpu.offscreen.1.py
+++ b/doc/python_api/examples/gpu.offscreen.1.py
@@ -52,6 +52,7 @@ class OffScreenDraw(bpy.types.Operator):
@staticmethod
def _update_offscreen(context, offscreen):
scene = context.scene
+ render_layer = context.render_layer
render = scene.render
camera = scene.camera
@@ -65,6 +66,7 @@ class OffScreenDraw(bpy.types.Operator):
offscreen.draw_view3d(
scene,
+ render_layer,
context.space_data,
context.region,
projection_matrix,
diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst
index 49f6c4469a4..3028ee653f8 100644
--- a/doc/python_api/rst/bge.texture.rst
+++ b/doc/python_api/rst/bge.texture.rst
@@ -681,7 +681,7 @@ Image classes
.. attribute:: zbuff
- Use depth component of render as grey scale color - suitable for texture source.
+ Use depth component of render as grayscale color - suitable for texture source.
:type: bool
@@ -817,7 +817,7 @@ Image classes
.. attribute:: zbuff
- Use depth component of viewport as grey scale color - suitable for texture source.
+ Use depth component of viewport as grayscale color - suitable for texture source.
:type: bool
@@ -1260,8 +1260,8 @@ Filter classes
.. class:: FilterGray
- Filter for gray scale effect.
- Proportions of R, G and B contributions in the output gray scale are 28:151:77.
+ Filter for grayscale effect.
+ Proportions of R, G and B contributions in the output grayscale are 28:151:77.
.. attribute:: previous
diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py
index ec3131ca19e..0316b6cd23e 100644
--- a/doc/python_api/sphinx_doc_gen.py
+++ b/doc/python_api/sphinx_doc_gen.py
@@ -427,9 +427,9 @@ if BLENDER_REVISION != "Unknown":
BLENDER_VERSION_DOTS += " " + BLENDER_REVISION # '2.62.1 SHA1'
BLENDER_VERSION_PATH = "_".join(blender_version_strings) # '2_62_1'
-if bpy.app.version_cycle == "release":
- BLENDER_VERSION_PATH = "%s%s_release" % ("_".join(blender_version_strings[:2]),
- bpy.app.version_char) # '2_62_release'
+if bpy.app.version_cycle in {"rc", "release"}:
+ # '2_62a_release'
+ BLENDER_VERSION_PATH = "%s%s_release" % ("_".join(blender_version_strings[:2]), bpy.app.version_char)
# --------------------------DOWNLOADABLE FILES----------------------------------
@@ -1024,6 +1024,7 @@ context_type_map = {
"brush": ("Brush", False),
"camera": ("Camera", False),
"cloth": ("ClothModifier", False),
+ "collection": ("LayerCollection", False),
"collision": ("CollisionModifier", False),
"curve": ("Curve", False),
"dynamic_paint": ("DynamicPaintModifier", False),
@@ -1055,6 +1056,7 @@ context_type_map = {
"particle_system": ("ParticleSystem", False),
"particle_system_editable": ("ParticleSystem", False),
"pose_bone": ("PoseBone", False),
+ "render_layer": ("SceneLayer", False),
"scene": ("Scene", False),
"sculpt_object": ("Object", False),
"selectable_bases": ("ObjectBase", True),
diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py
index 3d48c1145e1..561e58dec66 100755
--- a/doc/python_api/sphinx_doc_update.py
+++ b/doc/python_api/sphinx_doc_update.py
@@ -96,6 +96,11 @@ def main():
rsync_base = "rsync://%s@%s:%s" % (args.user, args.rsync_server, args.rsync_root)
+ blenver = blenver_zip = ""
+ api_name = ""
+ branch = ""
+ is_release = False
+
# I) Update local mirror using rsync.
rsync_mirror_cmd = ("rsync", "--delete-after", "-avzz", rsync_base, args.mirror_dir)
subprocess.run(rsync_mirror_cmd, env=dict(os.environ, RSYNC_PASSWORD=args.password))
@@ -108,19 +113,24 @@ def main():
subprocess.run(doc_gen_cmd)
# III) Get Blender version info.
- blenver = blenver_zip = ""
getver_file = os.path.join(tmp_dir, "blendver.txt")
getver_script = (""
"import sys, bpy\n"
"with open(sys.argv[-1], 'w') as f:\n"
- " f.write('%d_%d%s_release\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
- " if bpy.app.version_cycle in {'rc', 'release'} else '%d_%d_%d\\n' % bpy.app.version)\n"
- " f.write('%d_%d_%d' % bpy.app.version)\n")
+ " is_release = bpy.app.version_cycle in {'rc', 'release'}\n"
+ " branch = bpy.app.build_branch.split()[0].decode()\n"
+ " f.write('%d\\n' % is_release)\n"
+ " f.write('%s\\n' % branch)\n"
+ " f.write('%d.%d%s\\n' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
+ " if is_release else '%s\\n' % branch)\n"
+ " f.write('%d_%d%s_release' % (bpy.app.version[0], bpy.app.version[1], bpy.app.version_char)\n"
+ " if is_release else '%d_%d_%d' % bpy.app.version)\n")
get_ver_cmd = (args.blender, "--background", "-noaudio", "--factory-startup", "--python-exit-code", "1",
"--python-expr", getver_script, "--", getver_file)
subprocess.run(get_ver_cmd)
with open(getver_file) as f:
- blenver, blenver_zip = f.read().split("\n")
+ is_release, branch, blenver, blenver_zip = f.read().split("\n")
+ is_release = bool(int(is_release))
os.remove(getver_file)
# IV) Build doc.
@@ -132,7 +142,7 @@ def main():
os.chdir(curr_dir)
# V) Cleanup existing matching dir in server mirror (if any), and copy new doc.
- api_name = "blender_python_api_%s" % blenver
+ api_name = blenver
api_dir = os.path.join(args.mirror_dir, api_name)
if os.path.exists(api_dir):
shutil.rmtree(api_dir)
@@ -150,19 +160,15 @@ def main():
os.rename(zip_path, os.path.join(api_dir, "%s.zip" % zip_name))
# VII) Create symlinks and html redirects.
- #~ os.symlink(os.path.join(DEFAULT_SYMLINK_ROOT, api_name, "contents.html"), os.path.join(api_dir, "index.html"))
os.symlink("./contents.html", os.path.join(api_dir, "index.html"))
- if blenver.endswith("release"):
- symlink = os.path.join(args.mirror_dir, "blender_python_api_current")
+ if is_release:
+ symlink = os.path.join(args.mirror_dir, "current")
os.remove(symlink)
os.symlink("./%s" % api_name, symlink)
with open(os.path.join(args.mirror_dir, "250PythonDoc/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
- else:
- symlink = os.path.join(args.mirror_dir, "blender_python_api_master")
- os.remove(symlink)
- os.symlink("./%s" % api_name, symlink)
+ elif branch == "master":
with open(os.path.join(args.mirror_dir, "blender_python_api/index.html"), 'w') as f:
f.write("<html><head><title>Redirecting...</title><meta http-equiv=\"REFRESH\""
"content=\"0;url=../%s/\"></head><body>Redirecting...</body></html>" % api_name)
diff --git a/extern/clew/README.blender b/extern/clew/README.blender
index 8355a96db8e..127b6bdac63 100644
--- a/extern/clew/README.blender
+++ b/extern/clew/README.blender
@@ -1,5 +1,5 @@
Project: OpenCL Wrangler
URL: https://github.com/OpenCLWrangler/clew
License: Apache 2.0
-Upstream version: 309a653
+Upstream version: 27a6867
Local modifications: None
diff --git a/extern/clew/include/clew.h b/extern/clew/include/clew.h
index 2a583c81599..0bbb95b9839 100644
--- a/extern/clew/include/clew.h
+++ b/extern/clew/include/clew.h
@@ -369,7 +369,7 @@ typedef unsigned int cl_GLenum;
#endif
/* Define basic vector types */
-/* WOrkaround for ppc64el platform: conflicts with bool from C++. */
+/* Workaround for ppc64el platform: conflicts with bool from C++. */
#if defined( __VEC__ ) && !(defined(__PPC64__) && defined(__LITTLE_ENDIAN__))
#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
typedef vector unsigned char __cl_uchar16;
@@ -2765,11 +2765,40 @@ CLEW_FUN_EXPORT PFNCLGETGLCONTEXTINFOKHR __clewGetGLContextInfoKH
#define CL_DEVICE_GPU_OVERLAP_NV 0x4004
#define CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV 0x4005
#define CL_DEVICE_INTEGRATED_MEMORY_NV 0x4006
+#define CL_DEVICE_ATTRIBUTE_ASYNC_ENGINE_COUNT_NV 0x4007
+#define CL_DEVICE_PCI_BUS_ID_NV 0x4008
+#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009
/*********************************
* cl_amd_device_attribute_query *
*********************************/
#define CL_DEVICE_PROFILING_TIMER_OFFSET_AMD 0x4036
+#define CL_DEVICE_TOPOLOGY_AMD 0x4037
+#define CL_DEVICE_BOARD_NAME_AMD 0x4038
+#define CL_DEVICE_GLOBAL_FREE_MEMORY_AMD 0x4039
+#define CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD 0x4040
+#define CL_DEVICE_SIMD_WIDTH_AMD 0x4041
+#define CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD 0x4042
+#define CL_DEVICE_WAVEFRONT_WIDTH_AMD 0x4043
+#define CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD 0x4044
+#define CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD 0x4045
+#define CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD 0x4046
+#define CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD 0x4047
+#define CL_DEVICE_LOCAL_MEM_BANKS_AMD 0x4048
+#define CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD 0x4049
+#define CL_DEVICE_GFXIP_MAJOR_AMD 0x404A
+#define CL_DEVICE_GFXIP_MINOR_AMD 0x404B
+#define CL_DEVICE_AVAILABLE_ASYNC_QUEUES_AMD 0x404C
+
+#ifndef CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD
+#define CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD 1
+
+typedef union
+{
+ struct { cl_uint type; cl_uint data[5]; } raw;
+ struct { cl_uint type; cl_char unused[17]; cl_char bus; cl_char device; cl_char function; } pcie;
+} cl_device_topology_amd;
+#endif
/*********************************
* cl_arm_printf extension
diff --git a/extern/clew/src/clew.c b/extern/clew/src/clew.c
index 3717c74f1a0..dbdddfc0332 100644
--- a/extern/clew/src/clew.c
+++ b/extern/clew/src/clew.c
@@ -15,7 +15,7 @@
typedef HMODULE CLEW_DYNLIB_HANDLE;
- #define CLEW_DYNLIB_OPEN LoadLibrary
+ #define CLEW_DYNLIB_OPEN LoadLibraryA
#define CLEW_DYNLIB_CLOSE FreeLibrary
#define CLEW_DYNLIB_IMPORT GetProcAddress
#else
@@ -223,7 +223,7 @@ int clewInit()
__clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY )CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
#endif
__clewCreateBuffer = (PFNCLCREATEBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
+ __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER )CLEW_DYNLIB_IMPORT(module, "clCreateSubBuffer");
__clewCreateImage = (PFNCLCREATEIMAGE )CLEW_DYNLIB_IMPORT(module, "clCreateImage");
__clewRetainMemObject = (PFNCLRETAINMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
__clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT )CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
diff --git a/extern/cuew/include/cuew.h b/extern/cuew/include/cuew.h
index 19087117667..4cce29d38ab 100644
--- a/extern/cuew/include/cuew.h
+++ b/extern/cuew/include/cuew.h
@@ -114,7 +114,7 @@ extern "C" {
#define cuGLGetDevices cuGLGetDevices_v2
/* Types. */
-#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64)
+#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) || defined (__aarch64__)
typedef unsigned long long CUdeviceptr;
#else
typedef unsigned int CUdeviceptr;
diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt
index dd9889c81ba..af3b9296077 100644
--- a/intern/CMakeLists.txt
+++ b/intern/CMakeLists.txt
@@ -33,8 +33,9 @@ add_subdirectory(opencolorio)
add_subdirectory(mikktspace)
add_subdirectory(glew-mx)
add_subdirectory(eigen)
+add_subdirectory(gawain)
-if (WITH_GAMEENGINE_DECKLINK)
+if(WITH_GAMEENGINE_DECKLINK)
add_subdirectory(decklink)
endif()
diff --git a/intern/atomic/atomic_ops.h b/intern/atomic/atomic_ops.h
index 1107deddf94..1e9528f9ed9 100644
--- a/intern/atomic/atomic_ops.h
+++ b/intern/atomic/atomic_ops.h
@@ -101,11 +101,11 @@ ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_fetch_and_sub_z(size_t *p, size_t x);
ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new);
-ATOMIC_INLINE unsigned atomic_add_and_fetch_u(unsigned *p, unsigned x);
-ATOMIC_INLINE unsigned atomic_sub_and_fetch_u(unsigned *p, unsigned x);
-ATOMIC_INLINE unsigned atomic_fetch_and_add_u(unsigned *p, unsigned x);
-ATOMIC_INLINE unsigned atomic_fetch_and_sub_u(unsigned *p, unsigned x);
-ATOMIC_INLINE unsigned atomic_cas_u(unsigned *v, unsigned old, unsigned _new);
+ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x);
+ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x);
+ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int x);
+ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int x);
+ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsigned int _new);
/* WARNING! Float 'atomics' are really faked ones, those are actually closer to some kind of spinlock-sync'ed operation,
* which means they are only efficient if collisions are highly unlikely (i.e. if probability of two threads
diff --git a/intern/atomic/intern/atomic_ops_ext.h b/intern/atomic/intern/atomic_ops_ext.h
index 8421aa72192..b72c94563fc 100644
--- a/intern/atomic/intern/atomic_ops_ext.h
+++ b/intern/atomic/intern/atomic_ops_ext.h
@@ -113,58 +113,58 @@ ATOMIC_INLINE size_t atomic_cas_z(size_t *v, size_t old, size_t _new)
/******************************************************************************/
/* unsigned operations. */
-ATOMIC_INLINE unsigned atomic_add_and_fetch_u(unsigned *p, unsigned x)
+ATOMIC_INLINE unsigned int atomic_add_and_fetch_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned) == LG_SIZEOF_INT);
+ assert(sizeof(unsigned int) == LG_SIZEOF_INT);
#if (LG_SIZEOF_INT == 8)
- return (unsigned)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x);
+ return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_INT == 4)
- return (unsigned)atomic_add_and_fetch_uint32((uint32_t *)p, (uint32_t)x);
+ return (unsigned int)atomic_add_and_fetch_uint32((uint32_t *)p, (uint32_t)x);
#endif
}
-ATOMIC_INLINE unsigned atomic_sub_and_fetch_u(unsigned *p, unsigned x)
+ATOMIC_INLINE unsigned int atomic_sub_and_fetch_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned) == LG_SIZEOF_INT);
+ assert(sizeof(unsigned int) == LG_SIZEOF_INT);
#if (LG_SIZEOF_INT == 8)
- return (unsigned)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
+ return (unsigned int)atomic_add_and_fetch_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_INT == 4)
- return (unsigned)atomic_add_and_fetch_uint32((uint32_t *)p, (uint32_t)-((int32_t)x));
+ return (unsigned int)atomic_add_and_fetch_uint32((uint32_t *)p, (uint32_t)-((int32_t)x));
#endif
}
-ATOMIC_INLINE unsigned atomic_fetch_and_add_u(unsigned *p, unsigned x)
+ATOMIC_INLINE unsigned int atomic_fetch_and_add_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned) == LG_SIZEOF_INT);
+ assert(sizeof(unsigned int) == LG_SIZEOF_INT);
#if (LG_SIZEOF_INT == 8)
- return (unsigned)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x);
+ return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)x);
#elif (LG_SIZEOF_INT == 4)
- return (unsigned)atomic_fetch_and_add_uint32((uint32_t *)p, (uint32_t)x);
+ return (unsigned int)atomic_fetch_and_add_uint32((uint32_t *)p, (uint32_t)x);
#endif
}
-ATOMIC_INLINE unsigned atomic_fetch_and_sub_u(unsigned *p, unsigned x)
+ATOMIC_INLINE unsigned int atomic_fetch_and_sub_u(unsigned int *p, unsigned int x)
{
- assert(sizeof(unsigned) == LG_SIZEOF_INT);
+ assert(sizeof(unsigned int) == LG_SIZEOF_INT);
#if (LG_SIZEOF_INT == 8)
- return (unsigned)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
+ return (unsigned int)atomic_fetch_and_add_uint64((uint64_t *)p, (uint64_t)-((int64_t)x));
#elif (LG_SIZEOF_INT == 4)
- return (unsigned)atomic_fetch_and_add_uint32((uint32_t *)p, (uint32_t)-((int32_t)x));
+ return (unsigned int)atomic_fetch_and_add_uint32((uint32_t *)p, (uint32_t)-((int32_t)x));
#endif
}
-ATOMIC_INLINE unsigned atomic_cas_u(unsigned *v, unsigned old, unsigned _new)
+ATOMIC_INLINE unsigned int atomic_cas_u(unsigned int *v, unsigned int old, unsigned int _new)
{
- assert(sizeof(unsigned) == LG_SIZEOF_INT);
+ assert(sizeof(unsigned int) == LG_SIZEOF_INT);
#if (LG_SIZEOF_INT == 8)
- return (unsigned)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new);
+ return (unsigned int)atomic_cas_uint64((uint64_t *)v, (uint64_t)old, (uint64_t)_new);
#elif (LG_SIZEOF_INT == 4)
- return (unsigned)atomic_cas_uint32((uint32_t *)v, (uint32_t)old, (uint32_t)_new);
+ return (unsigned int)atomic_cas_uint32((uint32_t *)v, (uint32_t)old, (uint32_t)_new);
#endif
}
diff --git a/intern/audaspace/intern/AUD_SoftwareDevice.cpp b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
index 15594d340be..f9d65aa2363 100644
--- a/intern/audaspace/intern/AUD_SoftwareDevice.cpp
+++ b/intern/audaspace/intern/AUD_SoftwareDevice.cpp
@@ -365,6 +365,7 @@ bool AUD_SoftwareDevice::AUD_SoftwareHandle::seek(float position)
if(!m_status)
return false;
+ m_pitch->setPitch(m_user_pitch);
m_reader->seek((int)(position * m_reader->getSpecs().rate));
if(m_status == AUD_STATUS_STOPPED)
diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt
index 79c1c3e3e82..806a8660e8c 100644
--- a/intern/cycles/CMakeLists.txt
+++ b/intern/cycles/CMakeLists.txt
@@ -22,6 +22,7 @@ if(WITH_CYCLES_NATIVE_ONLY)
-DWITH_KERNEL_NATIVE
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+ set(CYCLES_KERNEL_FLAGS "-march=native")
elseif(NOT WITH_CPU_SSE)
set(CXX_HAS_SSE FALSE)
set(CXX_HAS_AVX FALSE)
@@ -59,10 +60,13 @@ elseif(WIN32 AND MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Ox")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Ox")
+
+ set(CYCLES_KERNEL_FLAGS "/fp:fast -D_CRT_SECURE_NO_WARNINGS /GS-")
elseif(CMAKE_COMPILER_IS_GNUCC)
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
+ set(CYCLES_KERNEL_FLAGS "-ffast-math")
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2 -mfpmath=sse")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse")
@@ -74,10 +78,12 @@ elseif(CMAKE_COMPILER_IS_GNUCC)
if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c -mfpmath=sse")
endif()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
check_cxx_compiler_flag(-msse CXX_HAS_SSE)
check_cxx_compiler_flag(-mavx CXX_HAS_AVX)
check_cxx_compiler_flag(-mavx2 CXX_HAS_AVX2)
+ set(CYCLES_KERNEL_FLAGS "-ffast-math")
if(CXX_HAS_SSE)
set(CYCLES_SSE2_KERNEL_FLAGS "-ffast-math -msse -msse2")
set(CYCLES_SSE3_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3")
@@ -89,6 +95,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(CXX_HAS_AVX2)
set(CYCLES_AVX2_KERNEL_FLAGS "-ffast-math -msse -msse2 -msse3 -mssse3 -msse4.1 -mavx -mavx2 -mfma -mlzcnt -mbmi -mbmi2 -mf16c")
endif()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffast-math -fno-finite-math-only")
endif()
if(CXX_HAS_SSE)
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index 8cd499b7ca6..aabb8f63640 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -1,14 +1,6 @@
set(INC
- .
- ../bvh
- ../device
- ../graph
- ../kernel
- ../kernel/svm
- ../render
- ../subd
- ../util
+ ..
)
set(INC_SYS
)
diff --git a/intern/cycles/app/cycles_server.cpp b/intern/cycles/app/cycles_server.cpp
index 4ef9cd070bb..e65b9d769e4 100644
--- a/intern/cycles/app/cycles_server.cpp
+++ b/intern/cycles/app/cycles_server.cpp
@@ -16,15 +16,15 @@
#include <stdio.h>
-#include "device.h"
-
-#include "util_args.h"
-#include "util_foreach.h"
-#include "util_path.h"
-#include "util_stats.h"
-#include "util_string.h"
-#include "util_task.h"
-#include "util_logging.h"
+#include "device/device.h"
+
+#include "util/util_args.h"
+#include "util/util_foreach.h"
+#include "util/util_path.h"
+#include "util/util_stats.h"
+#include "util/util_string.h"
+#include "util/util_task.h"
+#include "util/util_logging.h"
using namespace ccl;
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 9816d614a7c..0cd249f0d84 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -16,29 +16,29 @@
#include <stdio.h>
-#include "buffers.h"
-#include "camera.h"
-#include "device.h"
-#include "scene.h"
-#include "session.h"
-#include "integrator.h"
-
-#include "util_args.h"
-#include "util_foreach.h"
-#include "util_function.h"
-#include "util_logging.h"
-#include "util_path.h"
-#include "util_progress.h"
-#include "util_string.h"
-#include "util_time.h"
-#include "util_transform.h"
-#include "util_version.h"
+#include "render/buffers.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/scene.h"
+#include "render/session.h"
+#include "render/integrator.h"
+
+#include "util/util_args.h"
+#include "util/util_foreach.h"
+#include "util/util_function.h"
+#include "util/util_logging.h"
+#include "util/util_path.h"
+#include "util/util_progress.h"
+#include "util/util_string.h"
+#include "util/util_time.h"
+#include "util/util_transform.h"
+#include "util/util_version.h"
#ifdef WITH_CYCLES_STANDALONE_GUI
-#include "util_view.h"
+#include "util/util_view.h"
#endif
-#include "cycles_xml.h"
+#include "app/cycles_xml.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 35a30ae683f..04f00ef0e10 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -20,31 +20,31 @@
#include <algorithm>
#include <iterator>
-#include "node_xml.h"
-
-#include "background.h"
-#include "camera.h"
-#include "film.h"
-#include "graph.h"
-#include "integrator.h"
-#include "light.h"
-#include "mesh.h"
-#include "nodes.h"
-#include "object.h"
-#include "osl.h"
-#include "shader.h"
-#include "scene.h"
-
-#include "subd_patch.h"
-#include "subd_split.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_path.h"
-#include "util_transform.h"
-#include "util_xml.h"
-
-#include "cycles_xml.h"
+#include "graph/node_xml.h"
+
+#include "render/background.h"
+#include "render/camera.h"
+#include "render/film.h"
+#include "render/graph.h"
+#include "render/integrator.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/object.h"
+#include "render/osl.h"
+#include "render/shader.h"
+#include "render/scene.h"
+
+#include "subd/subd_patch.h"
+#include "subd/subd_split.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_path.h"
+#include "util/util_transform.h"
+#include "util/util_xml.h"
+
+#include "app/cycles_xml.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index b57502b3b14..ae4977aaed0 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -1,12 +1,6 @@
set(INC
- ../graph
- ../render
- ../device
- ../kernel
- ../kernel/svm
- ../util
- ../subd
+ ..
../../glew-mx
../../guardedalloc
../../mikktspace
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 235d19e91e8..eb792af7264 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -107,7 +107,13 @@ def engine_exit():
engine.exit()
+classes = (
+ CyclesRender,
+)
+
+
def register():
+ from bpy.utils import register_class
from . import ui
from . import properties
from . import presets
@@ -122,12 +128,15 @@ def register():
properties.register()
ui.register()
presets.register()
- bpy.utils.register_module(__name__)
+
+ for cls in classes:
+ register_class(cls)
bpy.app.handlers.version_update.append(version_update.do_versions)
def unregister():
+ from bpy.utils import unregister_class
from . import ui
from . import properties
from . import presets
@@ -138,4 +147,6 @@ def unregister():
ui.unregister()
properties.unregister()
presets.unregister()
- bpy.utils.unregister_module(__name__)
+
+ for cls in classes:
+ unregister_class(cls)
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index c8c9ef58c52..ab57dd44bdb 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -50,6 +50,24 @@ def _workaround_buggy_drivers():
_cycles.opencl_disable()
+def _configure_argument_parser():
+ import argparse
+ parser = argparse.ArgumentParser(description="Cycles Addon argument parser")
+ parser.add_argument("--cycles-resumable-num-chunks",
+ help="Number of chunks to split sample range into",
+ default=None)
+ parser.add_argument("--cycles-resumable-current-chunk",
+ help="Current chunk of samples range to render",
+ default=None)
+ parser.add_argument("--cycles-resumable-start-chunk",
+ help="Start chunk to render",
+ default=None)
+ parser.add_argument("--cycles-resumable-end-chunk",
+ help="End chunk to render",
+ default=None)
+ return parser
+
+
def _parse_command_line():
import sys
@@ -57,25 +75,22 @@ def _parse_command_line():
if "--" not in argv:
return
- argv = argv[argv.index("--") + 1:]
-
- num_resumable_chunks = None
- current_resumable_chunk = None
-
- # TODO(sergey): Add some nice error prints if argument is not used properly.
- idx = 0
- while idx < len(argv) - 1:
- arg = argv[idx]
- if arg == '--cycles-resumable-num-chunks':
- num_resumable_chunks = int(argv[idx + 1])
- elif arg == '--cycles-resumable-current-chunk':
- current_resumable_chunk = int(argv[idx + 1])
- idx += 1
+ parser = _configure_argument_parser()
+ args, unknown = parser.parse_known_args(argv[argv.index("--") + 1:])
- if num_resumable_chunks is not None and current_resumable_chunk is not None:
- import _cycles
- _cycles.set_resumable_chunks(num_resumable_chunks,
- current_resumable_chunk)
+ if args.cycles_resumable_num_chunks is not None:
+ if args.cycles_resumable_current_chunk is not None:
+ import _cycles
+ _cycles.set_resumable_chunk(
+ int(args.cycles_resumable_num_chunks),
+ int(args.cycles_resumable_current_chunk))
+ elif args.cycles_resumable_start_chunk is not None and \
+ args.cycles_resumable_end_chunk:
+ import _cycles
+ _cycles.set_resumable_chunk_range(
+ int(args.cycles_resumable_num_chunks),
+ int(args.cycles_resumable_start_chunk),
+ int(args.cycles_resumable_end_chunk))
def init():
diff --git a/intern/cycles/blender/addon/presets.py b/intern/cycles/blender/addon/presets.py
index f97b51b629d..82c4ffc6e50 100644
--- a/intern/cycles/blender/addon/presets.py
+++ b/intern/cycles/blender/addon/presets.py
@@ -82,12 +82,23 @@ class AddPresetSampling(AddPresetBase, Operator):
preset_subdir = "cycles/sampling"
+classes = (
+ AddPresetIntegrator,
+ AddPresetSampling,
+)
+
+
def register():
- pass
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
def unregister():
- pass
+ from bpy.utils import unregister_class
+ for cls in classes:
+ unregister_class(cls)
+
if __name__ == "__main__":
register()
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 5c51f9afc28..cbf469b3a89 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -665,8 +665,10 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True)
cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True)
cls.debug_use_qbvh = BoolProperty(name="QBVH", default=True)
+ cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False)
cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False)
+ cls.debug_use_cuda_split_kernel = BoolProperty(name="Split Kernel", default=False)
cls.debug_opencl_kernel_type = EnumProperty(
name="OpenCL Kernel Type",
@@ -693,6 +695,8 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
update=devices_update_callback
)
+ cls.debug_opencl_kernel_single_program = BoolProperty(name="Single Program", default=False, update=devices_update_callback);
+
cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
@classmethod
@@ -1092,6 +1096,12 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
default=1.0,
)
+ cls.is_shadow_catcher = BoolProperty(
+ name="Shadow Catcher",
+ description="Only render shadows on this object, for compositing renders into real footage",
+ default=False,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index eb89f0b1efa..39d918bd70f 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -86,12 +86,10 @@ def use_sample_all_lights(context):
return cscene.sample_all_lights_direct or cscene.sample_all_lights_indirect
-def show_device_selection(context):
- type = get_device_type(context)
- if type == 'NETWORK':
+def show_device_active(context):
+ cscene = context.scene.cycles
+ if cscene.device != 'GPU':
return True
- if not type in {'CUDA', 'OPENCL'}:
- return False
return context.user_preferences.addons[__package__].preferences.has_active_device()
@@ -186,9 +184,6 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
sub.label(text="AA Samples:")
sub.prop(cscene, "aa_samples", text="Render")
sub.prop(cscene, "preview_aa_samples", text="Preview")
- sub.separator()
- sub.prop(cscene, "sample_all_lights_direct")
- sub.prop(cscene, "sample_all_lights_indirect")
col = split.column()
sub = col.column(align=True)
@@ -205,6 +200,10 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
sub.prop(cscene, "subsurface_samples", text="Subsurface")
sub.prop(cscene, "volume_samples", text="Volume")
+ col = layout.column(align=True)
+ col.prop(cscene, "sample_all_lights_direct")
+ col.prop(cscene, "sample_all_lights_indirect")
+
if not (use_opencl(context) and cscene.feature_set != 'EXPERIMENTAL'):
layout.row().prop(cscene, "sampling_pattern", text="Pattern")
@@ -270,7 +269,7 @@ class CyclesRender_PT_geometry(CyclesButtonsPanel, Panel):
row = col.row()
row.prop(ccscene, "minimum_width", text="Min Pixels")
- row.prop(ccscene, "maximum_width", text="Max Ext.")
+ row.prop(ccscene, "maximum_width", text="Max Extension")
class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
@@ -788,6 +787,8 @@ class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
+ layout.prop(cob, "is_shadow_catcher")
+
col = layout.column()
col.label(text="Performance:")
row = col.row()
@@ -1518,15 +1519,18 @@ class CyclesRender_PT_debug(CyclesButtonsPanel, Panel):
row.prop(cscene, "debug_use_cpu_avx", toggle=True)
row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
col.prop(cscene, "debug_use_qbvh")
+ col.prop(cscene, "debug_use_cpu_split_kernel")
col = layout.column()
col.label('CUDA Flags:')
col.prop(cscene, "debug_use_cuda_adaptive_compile")
+ col.prop(cscene, "debug_use_cuda_split_kernel")
col = layout.column()
col.label('OpenCL Flags:')
col.prop(cscene, "debug_opencl_kernel_type", text="Kernel")
col.prop(cscene, "debug_opencl_device_type", text="Device")
+ col.prop(cscene, "debug_opencl_kernel_single_program", text="Single Program")
col.prop(cscene, "debug_use_opencl_debug", text="Debug")
@@ -1634,7 +1638,7 @@ def draw_device(self, context):
split = layout.split(percentage=1/3)
split.label("Device:")
row = split.row()
- row.active = show_device_selection(context)
+ row.active = show_device_active(context)
row.prop(cscene, "device", text="")
if engine.with_osl() and use_cpu(context):
@@ -1713,17 +1717,75 @@ def get_panels():
return panels
+
+classes = (
+ CYCLES_MT_sampling_presets,
+ CYCLES_MT_integrator_presets,
+ CyclesRender_PT_sampling,
+ CyclesRender_PT_geometry,
+ CyclesRender_PT_light_paths,
+ CyclesRender_PT_motion_blur,
+ CyclesRender_PT_film,
+ CyclesRender_PT_performance,
+ CyclesRender_PT_layer_options,
+ CyclesRender_PT_layer_passes,
+ CyclesRender_PT_views,
+ Cycles_PT_post_processing,
+ CyclesCamera_PT_dof,
+ Cycles_PT_context_material,
+ CyclesObject_PT_motion_blur,
+ CyclesObject_PT_cycles_settings,
+ CYCLES_OT_use_shading_nodes,
+ CyclesLamp_PT_preview,
+ CyclesLamp_PT_lamp,
+ CyclesLamp_PT_nodes,
+ CyclesLamp_PT_spot,
+ CyclesWorld_PT_preview,
+ CyclesWorld_PT_surface,
+ CyclesWorld_PT_volume,
+ CyclesWorld_PT_ambient_occlusion,
+ CyclesWorld_PT_mist,
+ CyclesWorld_PT_ray_visibility,
+ CyclesWorld_PT_settings,
+ CyclesMaterial_PT_preview,
+ CyclesMaterial_PT_surface,
+ CyclesMaterial_PT_volume,
+ CyclesMaterial_PT_displacement,
+ CyclesMaterial_PT_settings,
+ CyclesTexture_PT_context,
+ CyclesTexture_PT_node,
+ CyclesTexture_PT_mapping,
+ CyclesTexture_PT_colors,
+ CyclesParticle_PT_textures,
+ CyclesRender_PT_bake,
+ CyclesRender_PT_debug,
+ CyclesParticle_PT_CurveSettings,
+ CyclesScene_PT_simplify,
+)
+
+
def register():
+ from bpy.utils import register_class
+
bpy.types.RENDER_PT_render.append(draw_device)
bpy.types.VIEW3D_HT_header.append(draw_pause)
for panel in get_panels():
panel.COMPAT_ENGINES.add('CYCLES')
+ for cls in classes:
+ register_class(cls)
+
+
def unregister():
+ from bpy.utils import unregister_class
+
bpy.types.RENDER_PT_render.remove(draw_device)
bpy.types.VIEW3D_HT_header.remove(draw_pause)
for panel in get_panels():
if 'CYCLES' in panel.COMPAT_ENGINES:
panel.COMPAT_ENGINES.remove('CYCLES')
+
+ for cls in classes:
+ unregister_class(cls)
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp
index f02fc553908..40d6b25f2b7 100644
--- a/intern/cycles/blender/blender_camera.cpp
+++ b/intern/cycles/blender/blender_camera.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "scene.h"
+#include "render/camera.h"
+#include "render/scene.h"
-#include "blender_sync.h"
-#include "blender_util.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
-#include "util_logging.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index e42ff5d72a6..6fa038e8bf0 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-#include "attribute.h"
-#include "camera.h"
-#include "curves.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
+#include "render/attribute.h"
+#include "render/camera.h"
+#include "render/curves.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
-#include "blender_sync.h"
-#include "blender_util.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
-#include "util_foreach.h"
-#include "util_logging.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -411,6 +411,7 @@ static void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
}
}
+ mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size());
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -434,8 +435,8 @@ static void ExportCurveTriangleGeometry(Mesh *mesh,
if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
continue;
- numverts += (CData->curve_keynum[curve] - 2)*2*resolution + resolution;
- numtris += (CData->curve_keynum[curve] - 2)*resolution;
+ numverts += (CData->curve_keynum[curve] - 1)*resolution + resolution;
+ numtris += (CData->curve_keynum[curve] - 1)*2*resolution;
}
}
@@ -545,6 +546,7 @@ static void ExportCurveTriangleGeometry(Mesh *mesh,
}
}
+ mesh->resize_mesh(mesh->verts.size(), mesh->triangles.size());
mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
mesh->add_face_normals();
@@ -890,7 +892,7 @@ void BlenderSync::sync_curves(Mesh *mesh,
}
/* obtain general settings */
- bool use_curves = scene->curve_system_manager->use_curves;
+ const bool use_curves = scene->curve_system_manager->use_curves;
if(!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT)) {
if(!motion)
@@ -898,11 +900,11 @@ void BlenderSync::sync_curves(Mesh *mesh,
return;
}
- int primitive = scene->curve_system_manager->primitive;
- int triangle_method = scene->curve_system_manager->triangle_method;
- int resolution = scene->curve_system_manager->resolution;
- size_t vert_num = mesh->verts.size();
- size_t tri_num = mesh->num_triangles();
+ const int primitive = scene->curve_system_manager->primitive;
+ const int triangle_method = scene->curve_system_manager->triangle_method;
+ const int resolution = scene->curve_system_manager->resolution;
+ const size_t vert_num = mesh->verts.size();
+ const size_t tri_num = mesh->num_triangles();
int used_res = 1;
/* extract particle hair data - should be combined with connecting to mesh later*/
diff --git a/intern/cycles/blender/blender_logging.cpp b/intern/cycles/blender/blender_logging.cpp
index f4f86929168..d0f82e37662 100644
--- a/intern/cycles/blender/blender_logging.cpp
+++ b/intern/cycles/blender/blender_logging.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "CCL_api.h"
-#include "util_logging.h"
+#include "blender/CCL_api.h"
+#include "util/util_logging.h"
void CCL_init_logging(const char *argv0)
{
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 85117cfff7b..e0e89cec65c 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -15,21 +15,22 @@
*/
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "camera.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/camera.h"
-#include "blender_sync.h"
-#include "blender_session.h"
-#include "blender_util.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_session.h"
+#include "blender/blender_util.h"
-#include "subd_patch.h"
-#include "subd_split.h"
+#include "subd/subd_patch.h"
+#include "subd/subd_split.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_math.h"
+#include "util/util_algorithm.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_math.h"
#include "mikktspace.h"
@@ -525,69 +526,177 @@ static void attr_create_uv_map(Scene *scene,
}
/* Create vertex pointiness attributes. */
+
+/* Compare vertices by sum of their coordinates. */
+class VertexAverageComparator {
+public:
+ VertexAverageComparator(const array<float3>& verts)
+ : verts_(verts) {
+ }
+
+ bool operator()(const int& vert_idx_a, const int& vert_idx_b)
+ {
+ const float3 &vert_a = verts_[vert_idx_a];
+ const float3 &vert_b = verts_[vert_idx_b];
+ if(vert_a == vert_b) {
+ /* Special case for doubles, so we ensure ordering. */
+ return vert_idx_a > vert_idx_b;
+ }
+ const float x1 = vert_a.x + vert_a.y + vert_a.z;
+ const float x2 = vert_b.x + vert_b.y + vert_b.z;
+ return x1 < x2;
+ }
+
+protected:
+ const array<float3>& verts_;
+};
+
static void attr_create_pointiness(Scene *scene,
Mesh *mesh,
BL::Mesh& b_mesh,
bool subdivision)
{
- if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
- const int numverts = b_mesh.vertices.length();
- AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
- Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
- float *data = attr->data_float();
- int *counter = new int[numverts];
- float *raw_data = new float[numverts];
- float3 *edge_accum = new float3[numverts];
-
- /* Calculate pointiness using single ring neighborhood. */
- memset(counter, 0, sizeof(int) * numverts);
- memset(raw_data, 0, sizeof(float) * numverts);
- memset(edge_accum, 0, sizeof(float3) * numverts);
- BL::Mesh::edges_iterator e;
- int i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
- float3 co0 = get_float3(b_mesh.vertices[v0].co()),
- co1 = get_float3(b_mesh.vertices[v1].co());
- float3 edge = normalize(co1 - co0);
- edge_accum[v0] += edge;
- edge_accum[v1] += -edge;
- ++counter[v0];
- ++counter[v1];
- }
- i = 0;
- BL::Mesh::vertices_iterator v;
- for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
- if(counter[i] > 0) {
- float3 normal = get_float3(b_mesh.vertices[i].normal());
- float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
- raw_data[i] = angle * M_1_PI_F;
+ if(!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
+ return;
+ }
+ const int num_verts = b_mesh.vertices.length();
+ /* STEP 1: Find out duplicated vertices and point duplicates to a single
+ * original vertex.
+ */
+ vector<int> sorted_vert_indeices(num_verts);
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ sorted_vert_indeices[vert_index] = vert_index;
+ }
+ VertexAverageComparator compare(mesh->verts);
+ sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
+ /* This array stores index of the original vertex for the given vertex
+ * index.
+ */
+ vector<int> vert_orig_index(num_verts);
+ for(int sorted_vert_index = 0;
+ sorted_vert_index < num_verts;
+ ++sorted_vert_index)
+ {
+ const int vert_index = sorted_vert_indeices[sorted_vert_index];
+ const float3 &vert_co = mesh->verts[vert_index];
+ bool found = false;
+ for(int other_sorted_vert_index = sorted_vert_index + 1;
+ other_sorted_vert_index < num_verts;
+ ++other_sorted_vert_index)
+ {
+ const int other_vert_index =
+ sorted_vert_indeices[other_sorted_vert_index];
+ const float3 &other_vert_co = mesh->verts[other_vert_index];
+ /* We are too far away now, we wouldn't have duplicate. */
+ if((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
+ (vert_co.x + vert_co.y + vert_co.z) > 3 * FLT_EPSILON)
+ {
+ break;
}
- else {
- raw_data[i] = 0.0f;
+ /* Found duplicate. */
+ if(len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
+ found = true;
+ vert_orig_index[vert_index] = other_vert_index;
+ break;
}
}
-
- /* Blur vertices to approximate 2 ring neighborhood. */
- memset(counter, 0, sizeof(int) * numverts);
- memcpy(data, raw_data, sizeof(float) * numverts);
- i = 0;
- for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
- int v0 = b_mesh.edges[i].vertices()[0],
- v1 = b_mesh.edges[i].vertices()[1];
- data[v0] += raw_data[v1];
- data[v1] += raw_data[v0];
- ++counter[v0];
- ++counter[v1];
+ if(!found) {
+ vert_orig_index[vert_index] = vert_index;
+ }
+ }
+ /* Make sure we always points to the very first orig vertex. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ int orig_index = vert_orig_index[vert_index];
+ while(orig_index != vert_orig_index[orig_index]) {
+ orig_index = vert_orig_index[orig_index];
}
- for(i = 0; i < numverts; ++i) {
- data[i] /= counter[i] + 1;
+ vert_orig_index[vert_index] = orig_index;
+ }
+ sorted_vert_indeices.free_memory();
+ /* STEP 2: Calculate vertex normals taking into account their possible
+ * duplicates which gets "welded" together.
+ */
+ vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ /* First we accumulate all vertex normals in the original index. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[orig_index] += normal;
+ }
+ /* Then we normalize the accumulated result and flush it to all duplicates
+ * as well.
+ */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ vert_normal[vert_index] = normalize(vert_normal[orig_index]);
+ }
+ /* STEP 3: Calculate pointiness using single ring neighborhood. */
+ vector<int> counter(num_verts, 0);
+ vector<float> raw_data(num_verts, 0.0f);
+ vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
+ BL::Mesh::edges_iterator e;
+ EdgeMap visited_edges;
+ int edge_index = 0;
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if(visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ float3 co0 = get_float3(b_mesh.vertices[v0].co()),
+ co1 = get_float3(b_mesh.vertices[v1].co());
+ float3 edge = normalize(co1 - co0);
+ edge_accum[v0] += edge;
+ edge_accum[v1] += -edge;
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ if(orig_index != vert_index) {
+ /* Skip duplicates, they'll be overwritten later on. */
+ continue;
+ }
+ if(counter[vert_index] > 0) {
+ const float3 normal = vert_normal[vert_index];
+ const float angle =
+ safe_acosf(dot(normal,
+ edge_accum[vert_index] / counter[vert_index]));
+ raw_data[vert_index] = angle * M_1_PI_F;
+ }
+ else {
+ raw_data[vert_index] = 0.0f;
}
-
- delete [] counter;
- delete [] raw_data;
- delete [] edge_accum;
+ }
+ /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
+ AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
+ Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
+ float *data = attr->data_float();
+ memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
+ memset(&counter[0], 0, sizeof(int) * counter.size());
+ edge_index = 0;
+ visited_edges.clear();
+ for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
+ const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
+ v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
+ if(visited_edges.exists(v0, v1)) {
+ continue;
+ }
+ visited_edges.insert(v0, v1);
+ data[v0] += raw_data[v1];
+ data[v1] += raw_data[v0];
+ ++counter[v0];
+ ++counter[v1];
+ }
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ data[vert_index] /= counter[vert_index] + 1;
+ }
+ /* STEP 4: Copy attribute to the duplicated vertices. */
+ for(int vert_index = 0; vert_index < num_verts; ++vert_index) {
+ const int orig_index = vert_orig_index[vert_index];
+ data[vert_index] = data[orig_index];
}
}
@@ -656,9 +765,6 @@ static void create_mesh(Scene *scene,
generated[i++] = get_float3(v->undeformed_co())*size - loc;
}
- /* Create needed vertex attributes. */
- attr_create_pointiness(scene, mesh, b_mesh, subdivision);
-
/* create faces */
vector<int> nverts(numfaces);
vector<int> face_flags(numfaces, FACE_FLAG_NONE);
@@ -671,6 +777,15 @@ static void create_mesh(Scene *scene,
int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
bool smooth = f->use_smooth() || use_loop_normals;
+ if(use_loop_normals) {
+ BL::Array<float, 12> loop_normals = f->split_normals();
+ for(int i = 0; i < n; i++) {
+ N[vi[i]] = make_float3(loop_normals[i * 3],
+ loop_normals[i * 3 + 1],
+ loop_normals[i * 3 + 2]);
+ }
+ }
+
/* Create triangles.
*
* NOTE: Autosmooth is already taken care about.
@@ -704,7 +819,7 @@ static void create_mesh(Scene *scene,
int shader = clamp(p->material_index(), 0, used_shaders.size()-1);
bool smooth = p->use_smooth() || use_loop_normals;
- vi.reserve(n);
+ vi.resize(n);
for(int i = 0; i < n; i++) {
/* NOTE: Autosmooth is already taken care about. */
vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
@@ -718,6 +833,7 @@ static void create_mesh(Scene *scene,
/* Create all needed attributes.
* The calculate functions will check whether they're needed or not.
*/
+ attr_create_pointiness(scene, mesh, b_mesh, subdivision);
attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs);
@@ -1178,4 +1294,3 @@ void BlenderSync::sync_mesh_motion(BL::Object& b_ob,
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 637cf7abda8..d05699236cc 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -14,24 +14,24 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "integrator.h"
-#include "graph.h"
-#include "light.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "nodes.h"
-#include "particles.h"
-#include "shader.h"
-
-#include "blender_object_cull.h"
-#include "blender_sync.h"
-#include "blender_util.h"
-
-#include "util_foreach.h"
-#include "util_hash.h"
-#include "util_logging.h"
+#include "render/camera.h"
+#include "render/integrator.h"
+#include "render/graph.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/nodes.h"
+#include "render/particles.h"
+#include "render/shader.h"
+
+#include "blender/blender_object_cull.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
+
+#include "util/util_foreach.h"
+#include "util/util_hash.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -343,6 +343,13 @@ Object *BlenderSync::sync_object(BL::Object& b_parent,
object_updated = true;
}
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
+ if(is_shadow_catcher != object->is_shadow_catcher) {
+ object->is_shadow_catcher = is_shadow_catcher;
+ object_updated = true;
+ }
+
/* object sync
* transform comparison should not be needed, but duplis don't work perfect
* in the depsgraph and may not signal changes, so this is a workaround */
diff --git a/intern/cycles/blender/blender_object_cull.cpp b/intern/cycles/blender/blender_object_cull.cpp
index 08918dd1a49..0333c027f70 100644
--- a/intern/cycles/blender/blender_object_cull.cpp
+++ b/intern/cycles/blender/blender_object_cull.cpp
@@ -16,9 +16,9 @@
#include <cstdlib>
-#include "camera.h"
+#include "render/camera.h"
-#include "blender_object_cull.h"
+#include "blender/blender_object_cull.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_object_cull.h b/intern/cycles/blender/blender_object_cull.h
index b6f0ca5cd31..2147877a860 100644
--- a/intern/cycles/blender/blender_object_cull.h
+++ b/intern/cycles/blender/blender_object_cull.h
@@ -17,8 +17,8 @@
#ifndef __BLENDER_OBJECT_CULL_H__
#define __BLENDER_OBJECT_CULL_H__
-#include "blender_sync.h"
-#include "util_types.h"
+#include "blender/blender_sync.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index dd2900a8d5b..00f8cb3cf1b 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#include "mesh.h"
-#include "object.h"
-#include "particles.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/particles.h"
-#include "blender_sync.h"
-#include "blender_util.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
-#include "util_foreach.h"
+#include "util/util_foreach.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp
index 438abc49f88..d509e9de981 100644
--- a/intern/cycles/blender/blender_python.cpp
+++ b/intern/cycles/blender/blender_python.cpp
@@ -16,21 +16,21 @@
#include <Python.h>
-#include "CCL_api.h"
+#include "blender/CCL_api.h"
-#include "blender_sync.h"
-#include "blender_session.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_session.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_md5.h"
-#include "util_opengl.h"
-#include "util_path.h"
-#include "util_string.h"
-#include "util_types.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_opengl.h"
+#include "util/util_path.h"
+#include "util/util_string.h"
+#include "util/util_types.h"
#ifdef WITH_OSL
-#include "osl.h"
+#include "render/osl.h"
#include <OSL/oslquery.h>
#include <OSL/oslconfig.h>
@@ -67,8 +67,10 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
flags.cpu.qbvh = get_boolean(cscene, "debug_use_qbvh");
+ flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
/* Synchronize CUDA flags. */
flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
+ flags.cuda.split_kernel = get_boolean(cscene, "debug_use_cuda_split_kernel");
/* Synchronize OpenCL kernel type. */
switch(get_enum(cscene, "debug_opencl_kernel_type")) {
case 0:
@@ -104,6 +106,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
}
/* Synchronize other OpenCL flags. */
flags.opencl.debug = get_boolean(cscene, "debug_use_opencl_debug");
+ flags.opencl.single_program = get_boolean(cscene, "debug_opencl_kernel_single_program");
return flags.opencl.device_type != opencl_device_type ||
flags.opencl.kernel_type != opencl_kernel_type;
}
@@ -641,7 +644,7 @@ static PyObject *debug_flags_reset_func(PyObject * /*self*/, PyObject * /*args*/
Py_RETURN_NONE;
}
-static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args)
+static PyObject *set_resumable_chunk_func(PyObject * /*self*/, PyObject *args)
{
int num_resumable_chunks, current_resumable_chunk;
if(!PyArg_ParseTuple(args, "ii",
@@ -676,6 +679,53 @@ static PyObject *set_resumable_chunks_func(PyObject * /*self*/, PyObject *args)
Py_RETURN_NONE;
}
+static PyObject *set_resumable_chunk_range_func(PyObject * /*self*/, PyObject *args)
+{
+ int num_chunks, start_chunk, end_chunk;
+ if(!PyArg_ParseTuple(args, "iii",
+ &num_chunks,
+ &start_chunk,
+ &end_chunk)) {
+ Py_RETURN_NONE;
+ }
+
+ if(num_chunks <= 0) {
+ fprintf(stderr, "Cycles: Bad value for number of resumable chunks.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if(start_chunk < 1 || start_chunk > num_chunks) {
+ fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if(end_chunk < 1 || end_chunk > num_chunks) {
+ fprintf(stderr, "Cycles: Bad value for start chunk number.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+ if(start_chunk > end_chunk) {
+ fprintf(stderr, "Cycles: End chunk should be higher than start one.\n");
+ abort();
+ Py_RETURN_NONE;
+ }
+
+ VLOG(1) << "Initialized resumable render: "
+ << "num_resumable_chunks=" << num_chunks << ", "
+ << "start_resumable_chunk=" << start_chunk
+ << "end_resumable_chunk=" << end_chunk;
+ BlenderSession::num_resumable_chunks = num_chunks;
+ BlenderSession::start_resumable_chunk = start_chunk;
+ BlenderSession::end_resumable_chunk = end_chunk;
+
+ printf("Cycles: Will render chunks %d to %d of %d\n",
+ start_chunk,
+ end_chunk,
+ num_chunks);
+
+ Py_RETURN_NONE;
+}
+
static PyObject *get_device_types_func(PyObject * /*self*/, PyObject * /*args*/)
{
vector<DeviceInfo>& devices = Device::available_devices();
@@ -715,7 +765,8 @@ static PyMethodDef methods[] = {
{"debug_flags_reset", debug_flags_reset_func, METH_NOARGS, ""},
/* Resumable render */
- {"set_resumable_chunks", set_resumable_chunks_func, METH_VARARGS, ""},
+ {"set_resumable_chunk", set_resumable_chunk_func, METH_VARARGS, ""},
+ {"set_resumable_chunk_range", set_resumable_chunk_range_func, METH_VARARGS, ""},
/* Compute Device selection */
{"get_device_types", get_device_types_func, METH_VARARGS, ""},
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 2f30cbd961f..26f9bccd95d 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -16,36 +16,38 @@
#include <stdlib.h>
-#include "background.h"
-#include "buffers.h"
-#include "camera.h"
-#include "device.h"
-#include "integrator.h"
-#include "film.h"
-#include "light.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "session.h"
-#include "shader.h"
-
-#include "util_color.h"
-#include "util_foreach.h"
-#include "util_function.h"
-#include "util_hash.h"
-#include "util_logging.h"
-#include "util_progress.h"
-#include "util_time.h"
-
-#include "blender_sync.h"
-#include "blender_session.h"
-#include "blender_util.h"
+#include "render/background.h"
+#include "render/buffers.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/integrator.h"
+#include "render/film.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/session.h"
+#include "render/shader.h"
+
+#include "util/util_color.h"
+#include "util/util_foreach.h"
+#include "util/util_function.h"
+#include "util/util_hash.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
+#include "util/util_time.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_session.h"
+#include "blender/blender_util.h"
CCL_NAMESPACE_BEGIN
bool BlenderSession::headless = false;
int BlenderSession::num_resumable_chunks = 0;
int BlenderSession::current_resumable_chunk = 0;
+int BlenderSession::start_resumable_chunk = 0;
+int BlenderSession::end_resumable_chunk = 0;
BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
BL::UserPreferences& b_userpref,
@@ -68,6 +70,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
background = true;
last_redraw_time = 0.0;
start_resize_time = 0.0;
+ last_status_time = 0.0;
}
BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
@@ -93,6 +96,7 @@ BlenderSession::BlenderSession(BL::RenderEngine& b_engine,
background = false;
last_redraw_time = 0.0;
start_resize_time = 0.0;
+ last_status_time = 0.0;
}
BlenderSession::~BlenderSession()
@@ -989,10 +993,14 @@ void BlenderSession::update_status_progress()
if(substatus.size() > 0)
status += " | " + substatus;
- if(status != last_status) {
+ double current_time = time_dt();
+ /* When rendering in a window, redraw the status at least once per second to keep the elapsed and remaining time up-to-date.
+ * For headless rendering, only report when something significant changes to keep the console output readable. */
+ if(status != last_status || (!headless && (current_time - last_status_time) > 1.0)) {
b_engine.update_stats("", (timestatus + scene + status).c_str());
b_engine.update_memory_stats(mem_used, mem_peak);
last_status = status;
+ last_status_time = current_time;
}
if(progress != last_progress) {
b_engine.update_progress(progress);
@@ -1342,9 +1350,21 @@ void BlenderSession::update_resumable_tile_manager(int num_samples)
return;
}
- int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks);
- int range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
- int range_num_samples = num_samples_per_chunk;
+ const int num_samples_per_chunk = (int)ceilf((float)num_samples / num_resumable_chunks);
+
+ int range_start_sample, range_num_samples;
+ if(current_resumable_chunk != 0) {
+ /* Single chunk rendering. */
+ range_start_sample = num_samples_per_chunk * (current_resumable_chunk - 1);
+ range_num_samples = num_samples_per_chunk;
+ }
+ else {
+ /* Ranged-chunks. */
+ const int num_chunks = end_resumable_chunk - start_resumable_chunk + 1;
+ range_start_sample = num_samples_per_chunk * (start_resumable_chunk - 1);
+ range_num_samples = num_chunks * num_samples_per_chunk;
+ }
+ /* Make sure we don't overshoot. */
if(range_start_sample + range_num_samples > num_samples) {
range_num_samples = num_samples - range_num_samples;
}
diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h
index 82fe218b4ce..22b21a18f2e 100644
--- a/intern/cycles/blender/blender_session.h
+++ b/intern/cycles/blender/blender_session.h
@@ -17,12 +17,12 @@
#ifndef __BLENDER_SESSION_H__
#define __BLENDER_SESSION_H__
-#include "device.h"
-#include "scene.h"
-#include "session.h"
-#include "bake.h"
+#include "device/device.h"
+#include "render/scene.h"
+#include "render/session.h"
+#include "render/bake.h"
-#include "util_vector.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -113,6 +113,7 @@ public:
string last_status;
string last_error;
float last_progress;
+ double last_status_time;
int width, height;
double start_resize_time;
@@ -137,6 +138,10 @@ public:
/* Current resumable chunk index to render. */
static int current_resumable_chunk;
+ /* Alternative to single-chunk rendering to render a range of chunks. */
+ static int start_resumable_chunk;
+ static int end_resumable_chunk;
+
protected:
void do_write_update_render_result(BL::RenderResult& b_rr,
BL::RenderLayer& b_rlay,
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index f6ec015e1b8..3f04f11aab4 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -14,20 +14,23 @@
* limitations under the License.
*/
-#include "background.h"
-#include "graph.h"
-#include "light.h"
-#include "nodes.h"
-#include "osl.h"
-#include "scene.h"
-#include "shader.h"
-
-#include "blender_texture.h"
-#include "blender_sync.h"
-#include "blender_util.h"
-
-#include "util_debug.h"
-#include "util_string.h"
+#include "render/background.h"
+#include "render/graph.h"
+#include "render/light.h"
+#include "render/nodes.h"
+#include "render/osl.h"
+#include "render/scene.h"
+#include "render/shader.h"
+
+#include "blender/blender_texture.h"
+#include "blender/blender_sync.h"
+#include "blender/blender_util.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_string.h"
+#include "util/util_set.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -609,7 +612,8 @@ static ShaderNode *add_node(Scene *scene,
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
b_image.source() == BL::Image::source_MOVIE ||
- b_engine.is_preview();
+ (b_engine.is_preview() &&
+ b_image.source() != BL::Image::source_SEQUENCE);
if(is_builtin) {
/* for builtin images we're using image datablock name to find an image to
@@ -662,7 +666,8 @@ static ShaderNode *add_node(Scene *scene,
bool is_builtin = b_image.packed_file() ||
b_image.source() == BL::Image::source_GENERATED ||
b_image.source() == BL::Image::source_MOVIE ||
- b_engine.is_preview();
+ (b_engine.is_preview() &&
+ b_image.source() != BL::Image::source_SEQUENCE);
if(is_builtin) {
int scene_frame = b_scene.frame_current();
@@ -1162,6 +1167,9 @@ void BlenderSync::sync_materials(bool update_all)
/* material loop */
BL::BlendData::materials_iterator b_mat;
+ TaskPool pool;
+ set<Shader*> updated_shaders;
+
for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
Shader *shader;
@@ -1197,9 +1205,37 @@ void BlenderSync::sync_materials(bool update_all)
shader->displacement_method = (experimental) ? get_displacement_method(cmat) : DISPLACE_BUMP;
shader->set_graph(graph);
- shader->tag_update(scene);
+
+ /* By simplifying the shader graph as soon as possible, some
+ * redundant shader nodes might be removed which prevents loading
+ * unnecessary attributes later.
+ *
+ * However, since graph simplification also accounts for e.g. mix
+ * weight, this would cause frequent expensive resyncs in interactive
+ * sessions, so for those sessions optimization is only performed
+ * right before compiling.
+ */
+ if(!preview) {
+ pool.push(function_bind(&ShaderGraph::simplify, graph, scene));
+ /* NOTE: Update shaders out of the threads since those routines
+ * are accessing and writing to a global context.
+ */
+ updated_shaders.insert(shader);
+ }
+ else {
+ /* NOTE: Update tagging can access links which are being
+ * optimized out.
+ */
+ shader->tag_update(scene);
+ }
}
}
+
+ pool.wait_work();
+
+ foreach(Shader *shader, updated_shaders) {
+ shader->tag_update(scene);
+ }
}
/* Sync World */
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index d8043105cd8..3b071bf0e7d 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -14,29 +14,29 @@
* limitations under the License.
*/
-#include "background.h"
-#include "camera.h"
-#include "film.h"
-#include "graph.h"
-#include "integrator.h"
-#include "light.h"
-#include "mesh.h"
-#include "nodes.h"
-#include "object.h"
-#include "scene.h"
-#include "shader.h"
-#include "curves.h"
-
-#include "device.h"
-
-#include "blender_sync.h"
-#include "blender_session.h"
-#include "blender_util.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_opengl.h"
-#include "util_hash.h"
+#include "render/background.h"
+#include "render/camera.h"
+#include "render/film.h"
+#include "render/graph.h"
+#include "render/integrator.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/curves.h"
+
+#include "device/device.h"
+
+#include "blender/blender_sync.h"
+#include "blender/blender_session.h"
+#include "blender/blender_util.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_opengl.h"
+#include "util/util_hash.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 6984cbda259..36bedc505af 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -22,15 +22,15 @@
#include "RNA_access.h"
#include "RNA_blender_cpp.h"
-#include "blender_util.h"
+#include "blender/blender_util.h"
-#include "scene.h"
-#include "session.h"
+#include "render/scene.h"
+#include "render/session.h"
-#include "util_map.h"
-#include "util_set.h"
-#include "util_transform.h"
-#include "util_vector.h"
+#include "util/util_map.h"
+#include "util/util_set.h"
+#include "util/util_transform.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp
index 3807e683c7c..b2e27b76189 100644
--- a/intern/cycles/blender/blender_texture.cpp
+++ b/intern/cycles/blender/blender_texture.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "blender_texture.h"
+#include "blender/blender_texture.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h
index ad96f9db8ed..734231a85ec 100644
--- a/intern/cycles/blender/blender_texture.h
+++ b/intern/cycles/blender/blender_texture.h
@@ -18,7 +18,7 @@
#define __BLENDER_TEXTURE_H__
#include <stdlib.h>
-#include "blender_sync.h"
+#include "blender/blender_sync.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index b67834cdea3..abdbb6be0fd 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -17,14 +17,15 @@
#ifndef __BLENDER_UTIL_H__
#define __BLENDER_UTIL_H__
-#include "mesh.h"
+#include "render/mesh.h"
-#include "util_map.h"
-#include "util_path.h"
-#include "util_set.h"
-#include "util_transform.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_algorithm.h"
+#include "util/util_map.h"
+#include "util/util_path.h"
+#include "util/util_set.h"
+#include "util/util_transform.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
/* Hacks to hook into Blender API
* todo: clean this up ... */
@@ -78,7 +79,7 @@ static inline BL::Mesh object_to_mesh(BL::BlendData& data,
me.calc_normals_split();
}
else {
- me.split_faces();
+ me.split_faces(false);
}
}
if(subdivision_type == Mesh::SUBDIVISION_NONE) {
@@ -173,22 +174,19 @@ static inline void curvemapping_color_to_array(BL::CurveMapping& cumap,
if(rgb_curve) {
BL::CurveMap mapI = cumap.curves[3];
-
for(int i = 0; i < size; i++) {
- float t = min_x + (float)i/(float)(size-1) * range_x;
-
- data[i][0] = mapR.evaluate(mapI.evaluate(t));
- data[i][1] = mapG.evaluate(mapI.evaluate(t));
- data[i][2] = mapB.evaluate(mapI.evaluate(t));
+ const float t = min_x + (float)i/(float)(size-1) * range_x;
+ data[i] = make_float3(mapR.evaluate(mapI.evaluate(t)),
+ mapG.evaluate(mapI.evaluate(t)),
+ mapB.evaluate(mapI.evaluate(t)));
}
}
else {
for(int i = 0; i < size; i++) {
float t = min_x + (float)i/(float)(size-1) * range_x;
-
- data[i][0] = mapR.evaluate(t);
- data[i][1] = mapG.evaluate(t);
- data[i][2] = mapB.evaluate(t);
+ data[i] = make_float3(mapR.evaluate(t),
+ mapG.evaluate(t),
+ mapB.evaluate(t));
}
}
}
@@ -786,6 +784,35 @@ struct ParticleSystemKey {
}
};
+class EdgeMap {
+public:
+ EdgeMap() {
+ }
+
+ void clear() {
+ edges_.clear();
+ }
+
+ void insert(int v0, int v1) {
+ get_sorted_verts(v0, v1);
+ edges_.insert(std::pair<int, int>(v0, v1));
+ }
+
+ bool exists(int v0, int v1) {
+ get_sorted_verts(v0, v1);
+ return edges_.find(std::pair<int, int>(v0, v1)) != edges_.end();
+ }
+
+protected:
+ void get_sorted_verts(int& v0, int& v1) {
+ if(v0 > v1) {
+ swap(v0, v1);
+ }
+ }
+
+ set< std::pair<int, int> > edges_;
+};
+
CCL_NAMESPACE_END
#endif /* __BLENDER_UTIL_H__ */
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt
index 92e48f0d87f..4701d75350a 100644
--- a/intern/cycles/bvh/CMakeLists.txt
+++ b/intern/cycles/bvh/CMakeLists.txt
@@ -1,12 +1,6 @@
set(INC
- .
- ../graph
- ../kernel
- ../kernel/svm
- ../render
- ../util
- ../device
+ ..
)
set(INC_SYS
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 874a4246d1d..58348d16746 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -15,25 +15,25 @@
* limitations under the License.
*/
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "curves.h"
-
-#include "bvh.h"
-#include "bvh_build.h"
-#include "bvh_node.h"
-#include "bvh_params.h"
-#include "bvh_unaligned.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_map.h"
-#include "util_progress.h"
-#include "util_system.h"
-#include "util_types.h"
-#include "util_math.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/curves.h"
+
+#include "bvh/bvh.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_node.h"
+#include "bvh/bvh_params.h"
+#include "bvh/bvh_unaligned.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_progress.h"
+#include "util/util_system.h"
+#include "util/util_types.h"
+#include "util/util_math.h"
CCL_NAMESPACE_BEGIN
@@ -67,7 +67,7 @@ BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
if(params.use_qbvh)
return new QBVH(params, objects);
else
- return new RegularBVH(params, objects);
+ return new BinaryBVH(params, objects);
}
/* Building */
@@ -81,6 +81,7 @@ void BVH::build(Progress& progress)
pack.prim_type,
pack.prim_index,
pack.prim_object,
+ pack.prim_time,
params,
progress);
BVHNode *root = bvh_build.run();
@@ -256,6 +257,10 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
pack.leaf_nodes.resize(leaf_nodes_size);
pack.object_node.resize(objects.size());
+ if(params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) {
+ pack.prim_time.resize(prim_index_size);
+ }
+
int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL;
int *pack_prim_type = (pack.prim_type.size())? &pack.prim_type[0]: NULL;
int *pack_prim_object = (pack.prim_object.size())? &pack.prim_object[0]: NULL;
@@ -264,6 +269,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
uint *pack_prim_tri_index = (pack.prim_tri_index.size())? &pack.prim_tri_index[0]: NULL;
int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL;
int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL;
+ float2 *pack_prim_time = (pack.prim_time.size())? &pack.prim_time[0]: NULL;
/* merge */
foreach(Object *ob, objects) {
@@ -309,6 +315,7 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
int *bvh_prim_type = &bvh->pack.prim_type[0];
uint *bvh_prim_visibility = &bvh->pack.prim_visibility[0];
uint *bvh_prim_tri_index = &bvh->pack.prim_tri_index[0];
+ float2 *bvh_prim_time = bvh->pack.prim_time.size()? &bvh->pack.prim_time[0]: NULL;
for(size_t i = 0; i < bvh_prim_index_size; i++) {
if(bvh->pack.prim_type[i] & PRIMITIVE_ALL_CURVE) {
@@ -324,6 +331,9 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
pack_prim_type[pack_prim_index_offset] = bvh_prim_type[i];
pack_prim_visibility[pack_prim_index_offset] = bvh_prim_visibility[i];
pack_prim_object[pack_prim_index_offset] = 0; // unused for instances
+ if(bvh_prim_time != NULL) {
+ pack_prim_time[pack_prim_index_offset] = bvh_prim_time[i];
+ }
pack_prim_index_offset++;
}
}
@@ -414,64 +424,64 @@ static bool node_bvh_is_unaligned(const BVHNode *node)
{
const BVHNode *node0 = node->get_child(0),
*node1 = node->get_child(1);
- return node0->is_unaligned() || node1->is_unaligned();
+ return node0->is_unaligned || node1->is_unaligned;
}
-RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_)
+BinaryBVH::BinaryBVH(const BVHParams& params_, const vector<Object*>& objects_)
: BVH(params_, objects_)
{
}
-void RegularBVH::pack_leaf(const BVHStackEntry& e,
- const LeafNode *leaf)
+void BinaryBVH::pack_leaf(const BVHStackEntry& e,
+ const LeafNode *leaf)
{
assert(e.idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
float4 data[BVH_NODE_LEAF_SIZE];
memset(data, 0, sizeof(data));
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
/* object */
- data[0].x = __int_as_float(~(leaf->m_lo));
+ data[0].x = __int_as_float(~(leaf->lo));
data[0].y = __int_as_float(0);
}
else {
/* triangle */
- data[0].x = __int_as_float(leaf->m_lo);
- data[0].y = __int_as_float(leaf->m_hi);
+ data[0].x = __int_as_float(leaf->lo);
+ data[0].y = __int_as_float(leaf->hi);
}
- data[0].z = __uint_as_float(leaf->m_visibility);
+ data[0].z = __uint_as_float(leaf->visibility);
if(leaf->num_triangles() != 0) {
- data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
+ data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
}
memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_NODE_LEAF_SIZE);
}
-void RegularBVH::pack_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BinaryBVH::pack_inner(const BVHStackEntry& e,
+ const BVHStackEntry& e0,
+ const BVHStackEntry& e1)
{
- if(e0.node->is_unaligned() || e1.node->is_unaligned()) {
+ if(e0.node->is_unaligned || e1.node->is_unaligned) {
pack_unaligned_inner(e, e0, e1);
} else {
pack_aligned_inner(e, e0, e1);
}
}
-void RegularBVH::pack_aligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BinaryBVH::pack_aligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry& e0,
+ const BVHStackEntry& e1)
{
pack_aligned_node(e.idx,
- e0.node->m_bounds, e1.node->m_bounds,
+ e0.node->bounds, e1.node->bounds,
e0.encodeIdx(), e1.encodeIdx(),
- e0.node->m_visibility, e1.node->m_visibility);
+ e0.node->visibility, e1.node->visibility);
}
-void RegularBVH::pack_aligned_node(int idx,
- const BoundBox& b0,
- const BoundBox& b1,
- int c0, int c1,
- uint visibility0, uint visibility1)
+void BinaryBVH::pack_aligned_node(int idx,
+ const BoundBox& b0,
+ const BoundBox& b1,
+ int c0, int c1,
+ uint visibility0, uint visibility1)
{
assert(idx + BVH_NODE_SIZE <= pack.nodes.size());
assert(c0 < 0 || c0 < pack.nodes.size());
@@ -498,26 +508,26 @@ void RegularBVH::pack_aligned_node(int idx,
memcpy(&pack.nodes[idx], data, sizeof(int4)*BVH_NODE_SIZE);
}
-void RegularBVH::pack_unaligned_inner(const BVHStackEntry& e,
- const BVHStackEntry& e0,
- const BVHStackEntry& e1)
+void BinaryBVH::pack_unaligned_inner(const BVHStackEntry& e,
+ const BVHStackEntry& e0,
+ const BVHStackEntry& e1)
{
pack_unaligned_node(e.idx,
e0.node->get_aligned_space(),
e1.node->get_aligned_space(),
- e0.node->m_bounds,
- e1.node->m_bounds,
+ e0.node->bounds,
+ e1.node->bounds,
e0.encodeIdx(), e1.encodeIdx(),
- e0.node->m_visibility, e1.node->m_visibility);
+ e0.node->visibility, e1.node->visibility);
}
-void RegularBVH::pack_unaligned_node(int idx,
- const Transform& aligned_space0,
- const Transform& aligned_space1,
- const BoundBox& bounds0,
- const BoundBox& bounds1,
- int c0, int c1,
- uint visibility0, uint visibility1)
+void BinaryBVH::pack_unaligned_node(int idx,
+ const Transform& aligned_space0,
+ const Transform& aligned_space1,
+ const BoundBox& bounds0,
+ const BoundBox& bounds1,
+ int c0, int c1,
+ uint visibility0, uint visibility1)
{
assert(idx + BVH_UNALIGNED_NODE_SIZE <= pack.nodes.size());
assert(c0 < 0 || c0 < pack.nodes.size());
@@ -543,7 +553,7 @@ void RegularBVH::pack_unaligned_node(int idx,
memcpy(&pack.nodes[idx], data, sizeof(float4)*BVH_UNALIGNED_NODE_SIZE);
}
-void RegularBVH::pack_nodes(const BVHNode *root)
+void BinaryBVH::pack_nodes(const BVHNode *root)
{
const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT);
const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT);
@@ -620,7 +630,7 @@ void RegularBVH::pack_nodes(const BVHNode *root)
pack.root_index = (root->is_leaf())? -1: 0;
}
-void RegularBVH::refit_nodes()
+void BinaryBVH::refit_nodes()
{
assert(!params.top_level);
@@ -629,7 +639,7 @@ void RegularBVH::refit_nodes()
refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility);
}
-void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
+void BinaryBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
if(leaf) {
assert(idx + BVH_NODE_LEAF_SIZE <= pack.leaf_nodes.size());
@@ -759,18 +769,18 @@ static bool node_qbvh_is_unaligned(const BVHNode *node)
*node1 = node->get_child(1);
bool has_unaligned = false;
if(node0->is_leaf()) {
- has_unaligned |= node0->is_unaligned();
+ has_unaligned |= node0->is_unaligned;
}
else {
- has_unaligned |= node0->get_child(0)->is_unaligned();
- has_unaligned |= node0->get_child(1)->is_unaligned();
+ has_unaligned |= node0->get_child(0)->is_unaligned;
+ has_unaligned |= node0->get_child(1)->is_unaligned;
}
if(node1->is_leaf()) {
- has_unaligned |= node1->is_unaligned();
+ has_unaligned |= node1->is_unaligned;
}
else {
- has_unaligned |= node1->get_child(0)->is_unaligned();
- has_unaligned |= node1->get_child(1)->is_unaligned();
+ has_unaligned |= node1->get_child(0)->is_unaligned;
+ has_unaligned |= node1->get_child(1)->is_unaligned;
}
return has_unaligned;
}
@@ -785,19 +795,19 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
float4 data[BVH_QNODE_LEAF_SIZE];
memset(data, 0, sizeof(data));
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) {
/* object */
- data[0].x = __int_as_float(~(leaf->m_lo));
+ data[0].x = __int_as_float(~(leaf->lo));
data[0].y = __int_as_float(0);
}
else {
/* triangle */
- data[0].x = __int_as_float(leaf->m_lo);
- data[0].y = __int_as_float(leaf->m_hi);
+ data[0].x = __int_as_float(leaf->lo);
+ data[0].y = __int_as_float(leaf->hi);
}
- data[0].z = __uint_as_float(leaf->m_visibility);
+ data[0].z = __uint_as_float(leaf->visibility);
if(leaf->num_triangles() != 0) {
- data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
+ data[0].w = __uint_as_float(pack.prim_type[leaf->lo]);
}
memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
@@ -813,7 +823,7 @@ void QBVH::pack_inner(const BVHStackEntry& e,
*/
if(params.use_unaligned_nodes) {
for(int i = 0; i < num; i++) {
- if(en[i].node->is_unaligned()) {
+ if(en[i].node->is_unaligned) {
has_unaligned = true;
break;
}
@@ -838,15 +848,15 @@ void QBVH::pack_aligned_inner(const BVHStackEntry& e,
BoundBox bounds[4];
int child[4];
for(int i = 0; i < num; ++i) {
- bounds[i] = en[i].node->m_bounds;
+ bounds[i] = en[i].node->bounds;
child[i] = en[i].encodeIdx();
}
pack_aligned_node(e.idx,
bounds,
child,
- e.node->m_visibility,
- e.node->m_time_from,
- e.node->m_time_to,
+ e.node->visibility,
+ e.node->time_from,
+ e.node->time_to,
num);
}
@@ -907,16 +917,16 @@ void QBVH::pack_unaligned_inner(const BVHStackEntry& e,
int child[4];
for(int i = 0; i < num; ++i) {
aligned_space[i] = en[i].node->get_aligned_space();
- bounds[i] = en[i].node->m_bounds;
+ bounds[i] = en[i].node->bounds;
child[i] = en[i].encodeIdx();
}
pack_unaligned_node(e.idx,
aligned_space,
bounds,
child,
- e.node->m_visibility,
- e.node->m_time_from,
- e.node->m_time_to,
+ e.node->visibility,
+ e.node->time_from,
+ e.node->time_to,
num);
}
diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h
index 35f4d305883..60bc62ee6e4 100644
--- a/intern/cycles/bvh/bvh.h
+++ b/intern/cycles/bvh/bvh.h
@@ -18,10 +18,10 @@
#ifndef __BVH_H__
#define __BVH_H__
-#include "bvh_params.h"
+#include "bvh/bvh_params.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -68,6 +68,8 @@ struct PackedBVH {
array<int> prim_index;
/* mapping from BVH primitive index, to the object id of that primitive. */
array<int> prim_object;
+ /* Time range of BVH primitive. */
+ array<float2> prim_time;
/* index of the root node. */
int root_index;
@@ -108,15 +110,15 @@ protected:
virtual void refit_nodes() = 0;
};
-/* Regular BVH
+/* Binary BVH
*
* Typical BVH with each node having two children. */
-class RegularBVH : public BVH {
+class BinaryBVH : public BVH {
protected:
/* constructor */
friend class BVH;
- RegularBVH(const BVHParams& params, const vector<Object*>& objects);
+ BinaryBVH(const BVHParams& params, const vector<Object*>& objects);
/* pack */
void pack_nodes(const BVHNode *root);
diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp
index 5ddd7349f7b..3226008f511 100644
--- a/intern/cycles/bvh/bvh_binning.cpp
+++ b/intern/cycles/bvh/bvh_binning.cpp
@@ -19,11 +19,11 @@
#include <stdlib.h>
-#include "bvh_binning.h"
+#include "bvh/bvh_binning.h"
-#include "util_algorithm.h"
-#include "util_boundbox.h"
-#include "util_types.h"
+#include "util/util_algorithm.h"
+#include "util/util_boundbox.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_binning.h b/intern/cycles/bvh/bvh_binning.h
index 52955f70151..285f9c56a62 100644
--- a/intern/cycles/bvh/bvh_binning.h
+++ b/intern/cycles/bvh/bvh_binning.h
@@ -18,10 +18,10 @@
#ifndef __BVH_BINNING_H__
#define __BVH_BINNING_H__
-#include "bvh_params.h"
-#include "bvh_unaligned.h"
+#include "bvh/bvh_params.h"
+#include "bvh/bvh_unaligned.h"
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index a2f8b33cb0b..95c71b54da0 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -15,26 +15,26 @@
* limitations under the License.
*/
-#include "bvh_binning.h"
-#include "bvh_build.h"
-#include "bvh_node.h"
-#include "bvh_params.h"
+#include "bvh/bvh_binning.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_node.h"
+#include "bvh/bvh_params.h"
#include "bvh_split.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "curves.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_progress.h"
-#include "util_stack_allocator.h"
-#include "util_simd.h"
-#include "util_time.h"
-#include "util_queue.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/curves.h"
+
+#include "util/util_algorithm.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
+#include "util/util_stack_allocator.h"
+#include "util/util_simd.h"
+#include "util/util_time.h"
+#include "util/util_queue.h"
CCL_NAMESPACE_BEGIN
@@ -93,12 +93,14 @@ BVHBuild::BVHBuild(const vector<Object*>& objects_,
array<int>& prim_type_,
array<int>& prim_index_,
array<int>& prim_object_,
+ array<float2>& prim_time_,
const BVHParams& params_,
Progress& progress_)
: objects(objects_),
prim_type(prim_type_),
prim_index(prim_index_),
prim_object(prim_object_),
+ prim_time(prim_time_),
params(params_),
progress(progress_),
progress_start_time(0.0),
@@ -465,6 +467,9 @@ BVHNode* BVHBuild::run()
}
spatial_free_index = 0;
+ need_prim_time = params.num_motion_curve_steps > 0 ||
+ params.num_motion_triangle_steps > 0;
+
/* init progress updates */
double build_start_time;
build_start_time = progress_start_time = time_dt();
@@ -475,6 +480,12 @@ BVHNode* BVHBuild::run()
prim_type.resize(references.size());
prim_index.resize(references.size());
prim_object.resize(references.size());
+ if(need_prim_time) {
+ prim_time.resize(references.size());
+ }
+ else {
+ prim_time.resize(0);
+ }
/* build recursively */
BVHNode *rootnode;
@@ -849,11 +860,14 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
prim_type[start] = ref->prim_type();
prim_index[start] = ref->prim_index();
prim_object[start] = ref->prim_object();
+ if(need_prim_time) {
+ prim_time[start] = make_float2(ref->time_from(), ref->time_to());
+ }
uint visibility = objects[ref->prim_object()]->visibility;
BVHNode *leaf_node = new LeafNode(ref->bounds(), visibility, start, start+1);
- leaf_node->m_time_from = ref->time_from();
- leaf_node->m_time_to = ref->time_to();
+ leaf_node->time_from = ref->time_from();
+ leaf_node->time_to = ref->time_to();
return leaf_node;
}
else {
@@ -862,12 +876,12 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid);
BoundBox bounds = BoundBox::empty;
- bounds.grow(leaf0->m_bounds);
- bounds.grow(leaf1->m_bounds);
+ bounds.grow(leaf0->bounds);
+ bounds.grow(leaf1->bounds);
BVHNode *inner_node = new InnerNode(bounds, leaf0, leaf1);
- inner_node->m_time_from = min(leaf0->m_time_from, leaf1->m_time_from);
- inner_node->m_time_to = max(leaf0->m_time_to, leaf1->m_time_to);
+ inner_node->time_from = min(leaf0->time_from, leaf1->time_from);
+ inner_node->time_to = max(leaf0->time_to, leaf1->time_to);
return inner_node;
}
}
@@ -891,11 +905,13 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
* can not control.
*/
typedef StackAllocator<256, int> LeafStackAllocator;
+ typedef StackAllocator<256, float2> LeafTimeStackAllocator;
typedef StackAllocator<256, BVHReference> LeafReferenceStackAllocator;
vector<int, LeafStackAllocator> p_type[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_index[PRIMITIVE_NUM_TOTAL];
vector<int, LeafStackAllocator> p_object[PRIMITIVE_NUM_TOTAL];
+ vector<float2, LeafTimeStackAllocator> p_time[PRIMITIVE_NUM_TOTAL];
vector<BVHReference, LeafReferenceStackAllocator> p_ref[PRIMITIVE_NUM_TOTAL];
/* TODO(sergey): In theory we should be able to store references. */
@@ -918,6 +934,8 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
p_type[type_index].push_back(ref.prim_type());
p_index[type_index].push_back(ref.prim_index());
p_object[type_index].push_back(ref.prim_object());
+ p_time[type_index].push_back(make_float2(ref.time_from(),
+ ref.time_to()));
bounds[type_index].grow(ref.bounds());
visibility[type_index] |= objects[ref.prim_object()]->visibility;
@@ -947,9 +965,13 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
vector<int, LeafStackAllocator> local_prim_type,
local_prim_index,
local_prim_object;
+ vector<float2, LeafTimeStackAllocator> local_prim_time;
local_prim_type.resize(num_new_prims);
local_prim_index.resize(num_new_prims);
local_prim_object.resize(num_new_prims);
+ if(need_prim_time) {
+ local_prim_time.resize(num_new_prims);
+ }
for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
int num = (int)p_type[i].size();
if(num != 0) {
@@ -962,6 +984,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
local_prim_type[index] = p_type[i][j];
local_prim_index[index] = p_index[i][j];
local_prim_object[index] = p_object[i][j];
+ if(need_prim_time) {
+ local_prim_time[index] = p_time[i][j];
+ }
if(params.use_unaligned_nodes && !alignment_found) {
alignment_found =
unaligned_heuristic.compute_aligned_space(p_ref[i][j],
@@ -979,19 +1004,19 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
time_from = min(time_from, ref.time_from());
time_to = max(time_to, ref.time_to());
}
- leaf_node->m_time_from = time_from;
- leaf_node->m_time_to = time_to;
+ leaf_node->time_from = time_from;
+ leaf_node->time_to = time_to;
}
if(alignment_found) {
/* Need to recalculate leaf bounds with new alignment. */
- leaf_node->m_bounds = BoundBox::empty;
+ leaf_node->bounds = BoundBox::empty;
for(int j = 0; j < num; ++j) {
const BVHReference &ref = p_ref[i][j];
BoundBox ref_bounds =
unaligned_heuristic.compute_aligned_prim_boundbox(
ref,
aligned_space);
- leaf_node->m_bounds.grow(ref_bounds);
+ leaf_node->bounds.grow(ref_bounds);
}
/* Set alignment space. */
leaf_node->set_aligned_space(aligned_space);
@@ -1028,11 +1053,17 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
prim_type.reserve(reserve);
prim_index.reserve(reserve);
prim_object.reserve(reserve);
+ if(need_prim_time) {
+ prim_time.reserve(reserve);
+ }
}
prim_type.resize(range_end);
prim_index.resize(range_end);
prim_object.resize(range_end);
+ if(need_prim_time) {
+ prim_time.resize(range_end);
+ }
}
spatial_spin_lock.unlock();
@@ -1041,6 +1072,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if(need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
+ }
}
}
else {
@@ -1053,6 +1087,9 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
memcpy(&prim_type[start_index], &local_prim_type[0], new_leaf_data_size);
memcpy(&prim_index[start_index], &local_prim_index[0], new_leaf_data_size);
memcpy(&prim_object[start_index], &local_prim_object[0], new_leaf_data_size);
+ if(need_prim_time) {
+ memcpy(&prim_time[start_index], &local_prim_time[0], sizeof(float2)*num_new_leaf_data);
+ }
}
}
@@ -1062,8 +1099,8 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
*/
for(int i = 0; i < num_leaves; ++i) {
LeafNode *leaf = (LeafNode *)leaves[i];
- leaf->m_lo += start_index;
- leaf->m_hi += start_index;
+ leaf->lo += start_index;
+ leaf->hi += start_index;
}
/* Create leaf node for object. */
@@ -1092,17 +1129,17 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range,
return new InnerNode(range.bounds(), leaves[0], leaves[1]);
}
else if(num_leaves == 3) {
- BoundBox inner_bounds = merge(leaves[1]->m_bounds, leaves[2]->m_bounds);
+ BoundBox inner_bounds = merge(leaves[1]->bounds, leaves[2]->bounds);
BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
return new InnerNode(range.bounds(), leaves[0], inner);
} else {
/* Should be doing more branches if more primitive types added. */
assert(num_leaves <= 5);
- BoundBox inner_bounds_a = merge(leaves[0]->m_bounds, leaves[1]->m_bounds);
- BoundBox inner_bounds_b = merge(leaves[2]->m_bounds, leaves[3]->m_bounds);
+ BoundBox inner_bounds_a = merge(leaves[0]->bounds, leaves[1]->bounds);
+ BoundBox inner_bounds_b = merge(leaves[2]->bounds, leaves[3]->bounds);
BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
- BoundBox inner_bounds_c = merge(inner_a->m_bounds, inner_b->m_bounds);
+ BoundBox inner_bounds_c = merge(inner_a->bounds, inner_b->bounds);
BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b);
if(num_leaves == 5) {
return new InnerNode(range.bounds(), inner_c, leaves[4]);
@@ -1137,8 +1174,8 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
rotate(parent->children[c], max_depth-1);
/* compute current area of all children */
- BoundBox bounds0 = parent->children[0]->m_bounds;
- BoundBox bounds1 = parent->children[1]->m_bounds;
+ BoundBox bounds0 = parent->children[0]->bounds;
+ BoundBox bounds1 = parent->children[1]->bounds;
float area0 = bounds0.half_area();
float area1 = bounds1.half_area();
@@ -1158,8 +1195,8 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
BoundBox& other = (c == 0)? bounds1: bounds0;
/* transpose child bounds */
- BoundBox target0 = child->children[0]->m_bounds;
- BoundBox target1 = child->children[1]->m_bounds;
+ BoundBox target0 = child->children[0]->bounds;
+ BoundBox target1 = child->children[1]->bounds;
/* compute cost for both possible swaps */
float cost0 = merge(other, target1).half_area() - child_area[c];
@@ -1191,7 +1228,7 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
InnerNode *child = (InnerNode*)parent->children[best_child];
swap(parent->children[best_other], child->children[best_target]);
- child->m_bounds = merge(child->children[0]->m_bounds, child->children[1]->m_bounds);
+ child->bounds = merge(child->children[0]->bounds, child->children[1]->bounds);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index ee3cde66a2f..5733708050d 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -20,13 +20,13 @@
#include <float.h>
-#include "bvh.h"
-#include "bvh_binning.h"
-#include "bvh_unaligned.h"
+#include "bvh/bvh.h"
+#include "bvh/bvh_binning.h"
+#include "bvh/bvh_unaligned.h"
-#include "util_boundbox.h"
-#include "util_task.h"
-#include "util_vector.h"
+#include "util/util_boundbox.h"
+#include "util/util_task.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -48,6 +48,7 @@ public:
array<int>& prim_type,
array<int>& prim_index,
array<int>& prim_object,
+ array<float2>& prim_time,
const BVHParams& params,
Progress& progress);
~BVHBuild();
@@ -112,6 +113,9 @@ protected:
array<int>& prim_type;
array<int>& prim_index;
array<int>& prim_object;
+ array<float2>& prim_time;
+
+ bool need_prim_time;
/* Build parameters. */
BVHParams params;
diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp
index 67580e1bc7b..4f788c66797 100644
--- a/intern/cycles/bvh/bvh_node.cpp
+++ b/intern/cycles/bvh/bvh_node.cpp
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-#include "bvh.h"
-#include "bvh_build.h"
-#include "bvh_node.h"
+#include "bvh/bvh.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_node.h"
-#include "util_debug.h"
-#include "util_vector.h"
+#include "util/util_debug.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -62,12 +62,12 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
}
return cnt;
case BVH_STAT_ALIGNED_COUNT:
- if(!is_unaligned()) {
+ if(!is_unaligned) {
cnt = 1;
}
break;
case BVH_STAT_UNALIGNED_COUNT:
- if(is_unaligned()) {
+ if(is_unaligned) {
cnt = 1;
}
break;
@@ -75,7 +75,7 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
if(!is_leaf()) {
bool has_unaligned = false;
for(int j = 0; j < num_children(); j++) {
- has_unaligned |= get_child(j)->is_unaligned();
+ has_unaligned |= get_child(j)->is_unaligned;
}
cnt += has_unaligned? 0: 1;
}
@@ -84,7 +84,7 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
if(!is_leaf()) {
bool has_unaligned = false;
for(int j = 0; j < num_children(); j++) {
- has_unaligned |= get_child(j)->is_unaligned();
+ has_unaligned |= get_child(j)->is_unaligned;
}
cnt += has_unaligned? 1: 0;
}
@@ -95,12 +95,12 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
for(int i = 0; i < num_children(); i++) {
BVHNode *node = get_child(i);
if(node->is_leaf()) {
- has_unaligned |= node->is_unaligned();
+ has_unaligned |= node->is_unaligned;
}
else {
for(int j = 0; j < node->num_children(); j++) {
cnt += node->get_child(j)->getSubtreeSize(stat);
- has_unaligned |= node->get_child(j)->is_unaligned();
+ has_unaligned |= node->get_child(j)->is_unaligned;
}
}
}
@@ -113,12 +113,12 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
for(int i = 0; i < num_children(); i++) {
BVHNode *node = get_child(i);
if(node->is_leaf()) {
- has_unaligned |= node->is_unaligned();
+ has_unaligned |= node->is_unaligned;
}
else {
for(int j = 0; j < node->num_children(); j++) {
cnt += node->get_child(j)->getSubtreeSize(stat);
- has_unaligned |= node->get_child(j)->is_unaligned();
+ has_unaligned |= node->get_child(j)->is_unaligned;
}
}
}
@@ -126,10 +126,10 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const
}
return cnt;
case BVH_STAT_ALIGNED_LEAF_COUNT:
- cnt = (is_leaf() && !is_unaligned()) ? 1 : 0;
+ cnt = (is_leaf() && !is_unaligned) ? 1 : 0;
break;
case BVH_STAT_UNALIGNED_LEAF_COUNT:
- cnt = (is_leaf() && is_unaligned()) ? 1 : 0;
+ cnt = (is_leaf() && is_unaligned) ? 1 : 0;
break;
default:
assert(0); /* unknown mode */
@@ -157,7 +157,7 @@ float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) cons
for(int i = 0; i < num_children(); i++) {
BVHNode *child = get_child(i);
- SAH += child->computeSubtreeSAHCost(p, probability * child->m_bounds.safe_area()/m_bounds.safe_area());
+ SAH += child->computeSubtreeSAHCost(p, probability * child->bounds.safe_area()/bounds.safe_area());
}
return SAH;
@@ -165,15 +165,15 @@ float BVHNode::computeSubtreeSAHCost(const BVHParams& p, float probability) cons
uint BVHNode::update_visibility()
{
- if(!is_leaf() && m_visibility == 0) {
+ if(!is_leaf() && visibility == 0) {
InnerNode *inner = (InnerNode*)this;
BVHNode *child0 = inner->children[0];
BVHNode *child1 = inner->children[1];
- m_visibility = child0->update_visibility()|child1->update_visibility();
+ visibility = child0->update_visibility()|child1->update_visibility();
}
- return m_visibility;
+ return visibility;
}
void BVHNode::update_time()
@@ -184,8 +184,8 @@ void BVHNode::update_time()
BVHNode *child1 = inner->children[1];
child0->update_time();
child1->update_time();
- m_time_from = min(child0->m_time_from, child1->m_time_from);
- m_time_to = max(child0->m_time_to, child1->m_time_to);
+ time_from = min(child0->time_from, child1->time_from);
+ time_to = max(child0->time_to, child1->time_to);
}
}
@@ -209,7 +209,7 @@ void LeafNode::print(int depth) const
for(int i = 0; i < depth; i++)
printf(" ");
- printf("leaf node %d to %d\n", m_lo, m_hi);
+ printf("leaf node %d to %d\n", lo, hi);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h
index 090c426de56..60511b4b012 100644
--- a/intern/cycles/bvh/bvh_node.h
+++ b/intern/cycles/bvh/bvh_node.h
@@ -18,9 +18,9 @@
#ifndef __BVH_NODE_H__
#define __BVH_NODE_H__
-#include "util_boundbox.h"
-#include "util_debug.h"
-#include "util_types.h"
+#include "util/util_boundbox.h"
+#include "util/util_debug.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -46,16 +46,16 @@ class BVHParams;
class BVHNode
{
public:
- BVHNode() : m_is_unaligned(false),
- m_aligned_space(NULL),
- m_time_from(0.0f),
- m_time_to(1.0f)
+ BVHNode() : is_unaligned(false),
+ aligned_space(NULL),
+ time_from(0.0f),
+ time_to(1.0f)
{
}
virtual ~BVHNode()
{
- delete m_aligned_space;
+ delete aligned_space;
}
virtual bool is_leaf() const = 0;
@@ -63,30 +63,26 @@ public:
virtual BVHNode *get_child(int i) const = 0;
virtual int num_triangles() const { return 0; }
virtual void print(int depth = 0) const = 0;
- bool is_unaligned() const { return m_is_unaligned; }
inline void set_aligned_space(const Transform& aligned_space)
{
- m_is_unaligned = true;
- if(m_aligned_space == NULL) {
- m_aligned_space = new Transform(aligned_space);
+ is_unaligned = true;
+ if(this->aligned_space == NULL) {
+ this->aligned_space = new Transform(aligned_space);
}
else {
- *m_aligned_space = aligned_space;
+ *this->aligned_space = aligned_space;
}
}
inline Transform get_aligned_space() const
{
- if(m_aligned_space == NULL) {
+ if(aligned_space == NULL) {
return transform_identity();
}
- return *m_aligned_space;
+ return *aligned_space;
}
- BoundBox m_bounds;
- uint m_visibility;
-
// Subtree functions
int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const;
float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const;
@@ -95,13 +91,18 @@ public:
uint update_visibility();
void update_time();
- bool m_is_unaligned;
+ // Properties.
+ BoundBox bounds;
+ uint visibility;
+
+ bool is_unaligned;
- // TODO(sergey): Can be stored as 3x3 matrix, but better to have some
- // utilities and type defines in util_transform first.
- Transform *m_aligned_space;
+ /* TODO(sergey): Can be stored as 3x3 matrix, but better to have some
+ * utilities and type defines in util_transform first.
+ */
+ Transform *aligned_space;
- float m_time_from, m_time_to;
+ float time_from, time_to;
};
class InnerNode : public BVHNode
@@ -111,20 +112,20 @@ public:
BVHNode* child0,
BVHNode* child1)
{
- m_bounds = bounds;
+ this->bounds = bounds;
children[0] = child0;
children[1] = child1;
if(child0 && child1)
- m_visibility = child0->m_visibility|child1->m_visibility;
+ visibility = child0->visibility|child1->visibility;
else
- m_visibility = 0; /* happens on build cancel */
+ visibility = 0; /* happens on build cancel */
}
explicit InnerNode(const BoundBox& bounds)
{
- m_bounds = bounds;
- m_visibility = 0;
+ this->bounds = bounds;
+ visibility = 0;
children[0] = NULL;
children[1] = NULL;
}
@@ -140,12 +141,12 @@ public:
class LeafNode : public BVHNode
{
public:
- LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi)
+ LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi)
+ : lo(lo),
+ hi(hi)
{
- m_bounds = bounds;
- m_visibility = visibility;
- m_lo = lo;
- m_hi = hi;
+ this->bounds = bounds;
+ this->visibility = visibility;
}
LeafNode(const LeafNode& s)
@@ -157,14 +158,13 @@ public:
bool is_leaf() const { return true; }
int num_children() const { return 0; }
BVHNode *get_child(int) const { return NULL; }
- int num_triangles() const { return m_hi - m_lo; }
+ int num_triangles() const { return hi - lo; }
void print(int depth) const;
- int m_lo;
- int m_hi;
+ int lo;
+ int hi;
};
CCL_NAMESPACE_END
#endif /* __BVH_NODE_H__ */
-
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 65f9da1c194..9795a7a4350 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -18,9 +18,9 @@
#ifndef __BVH_PARAMS_H__
#define __BVH_PARAMS_H__
-#include "util_boundbox.h"
+#include "util/util_boundbox.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
CCL_NAMESPACE_BEGIN
@@ -104,6 +104,7 @@ public:
primitive_mask = PRIMITIVE_ALL;
num_motion_curve_steps = 0;
+ num_motion_triangle_steps = 0;
}
/* SAH costs */
diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp
index e5bcf9995bf..d29629c0279 100644
--- a/intern/cycles/bvh/bvh_sort.cpp
+++ b/intern/cycles/bvh/bvh_sort.cpp
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-#include "bvh_build.h"
-#include "bvh_sort.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_sort.h"
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_task.h"
+#include "util/util_algorithm.h"
+#include "util/util_debug.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp
index d0d5fbe5a7a..b10d69a495d 100644
--- a/intern/cycles/bvh/bvh_split.cpp
+++ b/intern/cycles/bvh/bvh_split.cpp
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-#include "bvh_build.h"
-#include "bvh_split.h"
-#include "bvh_sort.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_split.h"
+#include "bvh/bvh_sort.h"
-#include "mesh.h"
-#include "object.h"
+#include "render/mesh.h"
+#include "render/object.h"
-#include "util_algorithm.h"
+#include "util/util_algorithm.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h
index dbdb51f1a5b..a874a118b99 100644
--- a/intern/cycles/bvh/bvh_split.h
+++ b/intern/cycles/bvh/bvh_split.h
@@ -18,8 +18,8 @@
#ifndef __BVH_SPLIT_H__
#define __BVH_SPLIT_H__
-#include "bvh_build.h"
-#include "bvh_params.h"
+#include "bvh/bvh_build.h"
+#include "bvh/bvh_params.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp
index a876c670914..ef227d20ea9 100644
--- a/intern/cycles/bvh/bvh_unaligned.cpp
+++ b/intern/cycles/bvh/bvh_unaligned.cpp
@@ -15,17 +15,17 @@
*/
-#include "bvh_unaligned.h"
+#include "bvh/bvh_unaligned.h"
-#include "mesh.h"
-#include "object.h"
+#include "render/mesh.h"
+#include "render/object.h"
-#include "bvh_binning.h"
+#include "bvh/bvh_binning.h"
#include "bvh_params.h"
-#include "util_boundbox.h"
-#include "util_debug.h"
-#include "util_transform.h"
+#include "util/util_boundbox.h"
+#include "util/util_debug.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/bvh/bvh_unaligned.h b/intern/cycles/bvh/bvh_unaligned.h
index 4d0872f4a39..f41bae79e2b 100644
--- a/intern/cycles/bvh/bvh_unaligned.h
+++ b/intern/cycles/bvh/bvh_unaligned.h
@@ -17,7 +17,7 @@
#ifndef __BVH_UNALIGNED_H__
#define __BVH_UNALIGNED_H__
-#include "util_vector.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/device/CMakeLists.txt b/intern/cycles/device/CMakeLists.txt
index 966ff5e52ba..6ef2aa1caad 100644
--- a/intern/cycles/device/CMakeLists.txt
+++ b/intern/cycles/device/CMakeLists.txt
@@ -1,12 +1,6 @@
set(INC
- .
- ../graph
- ../kernel
- ../kernel/svm
- ../kernel/osl
- ../util
- ../render
+ ..
../../glew-mx
)
@@ -33,6 +27,7 @@ set(SRC
device_cuda.cpp
device_multi.cpp
device_opencl.cpp
+ device_split_kernel.cpp
device_task.cpp
)
@@ -56,6 +51,7 @@ set(SRC_HEADERS
device_memory.h
device_intern.h
device_network.h
+ device_split_kernel.h
device_task.h
)
diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp
index 31c99f49d6d..968af447e29 100644
--- a/intern/cycles/device/device.cpp
+++ b/intern/cycles/device/device.cpp
@@ -17,18 +17,18 @@
#include <stdlib.h>
#include <string.h>
-#include "device.h"
-#include "device_intern.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_half.h"
-#include "util_math.h"
-#include "util_opengl.h"
-#include "util_time.h"
-#include "util_types.h"
-#include "util_vector.h"
-#include "util_string.h"
+#include "device/device.h"
+#include "device/device_intern.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_half.h"
+#include "util/util_math.h"
+#include "util/util_opengl.h"
+#include "util/util_time.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
@@ -48,11 +48,11 @@ std::ostream& operator <<(std::ostream &os,
os << "Max nodes group: " << requested_features.max_nodes_group << std::endl;
/* TODO(sergey): Decode bitflag into list of names. */
os << "Nodes features: " << requested_features.nodes_features << std::endl;
- os << "Use hair: "
+ os << "Use Hair: "
<< string_from_bool(requested_features.use_hair) << std::endl;
- os << "Use object motion: "
+ os << "Use Object Motion: "
<< string_from_bool(requested_features.use_object_motion) << std::endl;
- os << "Use camera motion: "
+ os << "Use Camera Motion: "
<< string_from_bool(requested_features.use_camera_motion) << std::endl;
os << "Use Baking: "
<< string_from_bool(requested_features.use_baking) << std::endl;
@@ -80,7 +80,7 @@ Device::~Device()
void Device::pixels_alloc(device_memory& mem)
{
- mem_alloc(mem, MEM_READ_WRITE);
+ mem_alloc("pixels", mem, MEM_READ_WRITE);
}
void Device::pixels_copy_from(device_memory& mem, int y, int w, int h)
diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h
index ccee25ae34e..ac06e561795 100644
--- a/intern/cycles/device/device.h
+++ b/intern/cycles/device/device.h
@@ -19,15 +19,15 @@
#include <stdlib.h>
-#include "device_memory.h"
-#include "device_task.h"
+#include "device/device_memory.h"
+#include "device/device_task.h"
-#include "util_list.h"
-#include "util_stats.h"
-#include "util_string.h"
-#include "util_thread.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_list.h"
+#include "util/util_stats.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -121,6 +121,9 @@ public:
/* Use Transparent shadows */
bool use_transparent;
+ /* Use various shadow tricks, such as shadow catcher. */
+ bool use_shadow_tricks;
+
DeviceRequestedFeatures()
{
/* TODO(sergey): Find more meaningful defaults. */
@@ -137,6 +140,7 @@ public:
use_integrator_branched = false;
use_patch_evaluation = false;
use_transparent = false;
+ use_shadow_tricks = false;
}
bool modified(const DeviceRequestedFeatures& requested_features)
@@ -153,7 +157,8 @@ public:
use_volume == requested_features.use_volume &&
use_integrator_branched == requested_features.use_integrator_branched &&
use_patch_evaluation == requested_features.use_patch_evaluation &&
- use_transparent == requested_features.use_transparent);
+ use_transparent == requested_features.use_transparent &&
+ use_shadow_tricks == requested_features.use_shadow_tricks);
}
/* Convert the requested features structure to a build options,
@@ -194,9 +199,12 @@ public:
if(!use_patch_evaluation) {
build_options += " -D__NO_PATCH_EVAL__";
}
- if(!use_transparent) {
+ if(!use_transparent && !use_volume) {
build_options += " -D__NO_TRANSPARENT__";
}
+ if(!use_shadow_tricks) {
+ build_options += " -D__NO_SHADOW_TRICKS__";
+ }
return build_options;
}
};
@@ -228,13 +236,21 @@ public:
DeviceInfo info;
virtual const string& error_message() { return error_msg; }
bool have_error() { return !error_message().empty(); }
+ virtual void set_error(const string& error)
+ {
+ if(!have_error()) {
+ error_msg = error;
+ }
+ fprintf(stderr, "%s\n", error.c_str());
+ fflush(stderr);
+ }
virtual bool show_samples() const { return false; }
/* statistics */
Stats &stats;
/* regular memory */
- virtual void mem_alloc(device_memory& mem, MemoryType type) = 0;
+ virtual void mem_alloc(const char *name, device_memory& mem, MemoryType type) = 0;
virtual void mem_copy_to(device_memory& mem) = 0;
virtual void mem_copy_from(device_memory& mem,
int y, int w, int h, int elem) = 0;
diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp
index c8e001ec2fd..2761d9488ca 100644
--- a/intern/cycles/device/device_cpu.cpp
+++ b/intern/cycles/device/device_cpu.cpp
@@ -20,36 +20,124 @@
/* So ImathMath is included before our kernel_cpu_compat. */
#ifdef WITH_OSL
/* So no context pollution happens from indirectly included windows.h */
-# include "util_windows.h"
+# include "util/util_windows.h"
# include <OSL/oslexec.h>
#endif
-#include "device.h"
-#include "device_intern.h"
+#include "device/device.h"
+#include "device/device_intern.h"
+#include "device/device_split_kernel.h"
-#include "kernel.h"
-#include "kernel_compat_cpu.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
+#include "kernel/kernel.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/kernel_types.h"
+#include "kernel/split/kernel_split_data.h"
+#include "kernel/kernel_globals.h"
-#include "osl_shader.h"
-#include "osl_globals.h"
+#include "kernel/osl/osl_shader.h"
+#include "kernel/osl/osl_globals.h"
-#include "buffers.h"
+#include "render/buffers.h"
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_function.h"
-#include "util_logging.h"
-#include "util_opengl.h"
-#include "util_progress.h"
-#include "util_system.h"
-#include "util_thread.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_function.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_opengl.h"
+#include "util/util_progress.h"
+#include "util/util_system.h"
+#include "util/util_thread.h"
CCL_NAMESPACE_BEGIN
+class CPUDevice;
+
+class CPUSplitKernel : public DeviceSplitKernel {
+ CPUDevice *device;
+public:
+ explicit CPUSplitKernel(CPUDevice *device);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& kernel_globals,
+ device_memory& kernel_data_,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flag,
+ device_memory& work_pool_wgs);
+
+ virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
+ virtual int2 split_kernel_local_size();
+ virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
+ virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
+};
+
class CPUDevice : public Device
{
+ static unordered_map<string, void*> kernel_functions;
+
+ static void register_kernel_function(const char* name, void* func)
+ {
+ kernel_functions[name] = func;
+ }
+
+ static const char* get_arch_name()
+ {
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+ if(system_cpu_support_avx2()) {
+ return "cpu_avx2";
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
+ if(system_cpu_support_avx()) {
+ return "cpu_avx";
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ return "cpu_sse41";
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+ if(system_cpu_support_sse3()) {
+ return "cpu_sse3";
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
+ if(system_cpu_support_sse2()) {
+ return "cpu_sse2";
+ }
+ else
+#endif
+ {
+ return "cpu";
+ }
+ }
+
+ template<typename F>
+ static F get_kernel_function(string name)
+ {
+ name = string("kernel_") + get_arch_name() + "_" + name;
+
+ unordered_map<string, void*>::iterator it = kernel_functions.find(name);
+
+ if(it == kernel_functions.end()) {
+ assert(!"kernel function not found");
+ return NULL;
+ }
+
+ return (F)it->second;
+ }
+
+ friend class CPUSplitKernel;
+
public:
TaskPool task_pool;
KernelGlobals kernel_globals;
@@ -57,10 +145,15 @@ public:
#ifdef WITH_OSL
OSLGlobals osl_globals;
#endif
+
+ bool use_split_kernel;
+
+ DeviceRequestedFeatures requested_features;
CPUDevice(DeviceInfo& info, Stats &stats, bool background)
: Device(info, stats, background)
{
+
#ifdef WITH_OSL
kernel_globals.osl = &osl_globals;
#endif
@@ -105,6 +198,28 @@ public:
{
VLOG(1) << "Will be using regular kernels.";
}
+
+ use_split_kernel = DebugFlags().cpu.split_kernel;
+ if(use_split_kernel) {
+ VLOG(1) << "Will be using split kernel.";
+ }
+
+ kernel_cpu_register_functions(register_kernel_function);
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
+ kernel_cpu_sse2_register_functions(register_kernel_function);
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+ kernel_cpu_sse3_register_functions(register_kernel_function);
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ kernel_cpu_sse41_register_functions(register_kernel_function);
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
+ kernel_cpu_avx_register_functions(register_kernel_function);
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+ kernel_cpu_avx2_register_functions(register_kernel_function);
+#endif
}
~CPUDevice()
@@ -117,9 +232,20 @@ public:
return (TaskScheduler::num_threads() == 1);
}
- void mem_alloc(device_memory& mem, MemoryType /*type*/)
+ void mem_alloc(const char *name, device_memory& mem, MemoryType /*type*/)
{
+ if(name) {
+ VLOG(1) << "Buffer allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
mem.device_pointer = mem.data_pointer;
+
+ if(!mem.device_pointer) {
+ mem.device_pointer = (device_ptr)malloc(mem.memory_size());
+ }
+
mem.device_size = mem.memory_size();
stats.mem_alloc(mem.device_size);
}
@@ -144,6 +270,10 @@ public:
void mem_free(device_memory& mem)
{
if(mem.device_pointer) {
+ if(!mem.data_pointer) {
+ free((void*)mem.device_pointer);
+ }
+
mem.device_pointer = 0;
stats.mem_free(mem.device_size);
mem.device_size = 0;
@@ -196,8 +326,14 @@ public:
void thread_run(DeviceTask *task)
{
- if(task->type == DeviceTask::PATH_TRACE)
- thread_path_trace(*task);
+ if(task->type == DeviceTask::PATH_TRACE) {
+ if(!use_split_kernel) {
+ thread_path_trace(*task);
+ }
+ else {
+ thread_path_trace_split(*task);
+ }
+ }
else if(task->type == DeviceTask::FILM_CONVERT)
thread_film_convert(*task);
else if(task->type == DeviceTask::SHADER)
@@ -258,7 +394,7 @@ public:
{
path_trace_kernel = kernel_cpu_path_trace;
}
-
+
while(task.acquire_tile(this, tile)) {
float *render_buffer = (float*)tile.buffer;
uint *rng_state = (uint*)tile.rng_state;
@@ -294,6 +430,49 @@ public:
thread_kernel_globals_free(&kg);
}
+ void thread_path_trace_split(DeviceTask& task)
+ {
+ if(task_pool.canceled()) {
+ if(task.need_finish_queue == false)
+ return;
+ }
+
+ RenderTile tile;
+
+ CPUSplitKernel split_kernel(this);
+
+ /* allocate buffer for kernel globals */
+ device_memory kgbuffer;
+ kgbuffer.resize(sizeof(KernelGlobals));
+ mem_alloc("kernel_globals", kgbuffer, MEM_READ_WRITE);
+
+ KernelGlobals *kg = (KernelGlobals*)kgbuffer.device_pointer;
+ *kg = thread_kernel_globals_init();
+
+ requested_features.max_closure = MAX_CLOSURE;
+ if(!split_kernel.load_kernels(requested_features)) {
+ thread_kernel_globals_free((KernelGlobals*)kgbuffer.device_pointer);
+ mem_free(kgbuffer);
+
+ return;
+ }
+
+ while(task.acquire_tile(this, tile)) {
+ device_memory data;
+ split_kernel.path_trace(&task, tile, kgbuffer, data);
+
+ task.release_tile(tile);
+
+ if(task_pool.canceled()) {
+ if(task.need_finish_queue == false)
+ break;
+ }
+ }
+
+ thread_kernel_globals_free((KernelGlobals*)kgbuffer.device_pointer);
+ mem_free(kgbuffer);
+ }
+
void thread_film_convert(DeviceTask& task)
{
float sample_scale = 1.0f/(task.sample + 1);
@@ -501,6 +680,10 @@ protected:
inline void thread_kernel_globals_free(KernelGlobals *kg)
{
+ if(kg == NULL) {
+ return;
+ }
+
if(kg->transparent_shadow_intersections != NULL) {
free(kg->transparent_shadow_intersections);
}
@@ -515,8 +698,175 @@ protected:
OSLShader::thread_free(kg);
#endif
}
+
+ virtual bool load_kernels(DeviceRequestedFeatures& requested_features_) {
+ requested_features = requested_features_;
+
+ return true;
+ }
+};
+
+/* split kernel */
+
+class CPUSplitKernelFunction : public SplitKernelFunction {
+public:
+ CPUDevice* device;
+ void (*func)(KernelGlobals *kg, KernelData *data);
+
+ CPUSplitKernelFunction(CPUDevice* device) : device(device), func(NULL) {}
+ ~CPUSplitKernelFunction() {}
+
+ virtual bool enqueue(const KernelDimensions& dim, device_memory& kernel_globals, device_memory& data)
+ {
+ if(!func) {
+ return false;
+ }
+
+ KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
+ kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
+
+ for(int y = 0; y < dim.global_size[1]; y++) {
+ for(int x = 0; x < dim.global_size[0]; x++) {
+ kg->global_id = make_int2(x, y);
+
+ func(kg, (KernelData*)data.device_pointer);
+ }
+ }
+
+ return true;
+ }
};
+CPUSplitKernel::CPUSplitKernel(CPUDevice *device) : DeviceSplitKernel(device), device(device)
+{
+}
+
+bool CPUSplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& kernel_globals,
+ device_memory& data,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flags,
+ device_memory& work_pool_wgs)
+{
+ typedef void(*data_init_t)(KernelGlobals *kg,
+ ccl_constant KernelData *data,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
+ ccl_global uint *rng_state,
+ int start_sample,
+ int end_sample,
+ int sx, int sy, int sw, int sh, int offset, int stride,
+ ccl_global int *Queue_index,
+ int queuesize,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+ ccl_global float *buffer);
+
+ data_init_t data_init;
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+ if(system_cpu_support_avx2()) {
+ data_init = kernel_cpu_avx2_data_init;
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
+ if(system_cpu_support_avx()) {
+ data_init = kernel_cpu_avx_data_init;
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+ if(system_cpu_support_sse41()) {
+ data_init = kernel_cpu_sse41_data_init;
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+ if(system_cpu_support_sse3()) {
+ data_init = kernel_cpu_sse3_data_init;
+ }
+ else
+#endif
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
+ if(system_cpu_support_sse2()) {
+ data_init = kernel_cpu_sse2_data_init;
+ }
+ else
+#endif
+ {
+ data_init = kernel_cpu_data_init;
+ }
+
+ KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
+ kg->global_size = make_int2(dim.global_size[0], dim.global_size[1]);
+
+ for(int y = 0; y < dim.global_size[1]; y++) {
+ for(int x = 0; x < dim.global_size[0]; x++) {
+ kg->global_id = make_int2(x, y);
+
+ data_init((KernelGlobals*)kernel_globals.device_pointer,
+ (KernelData*)data.device_pointer,
+ (void*)split_data.device_pointer,
+ num_global_elements,
+ (char*)ray_state.device_pointer,
+ (uint*)rtile.rng_state,
+ rtile.start_sample,
+ rtile.start_sample + rtile.num_samples,
+ rtile.x,
+ rtile.y,
+ rtile.w,
+ rtile.h,
+ rtile.offset,
+ rtile.stride,
+ (int*)queue_index.device_pointer,
+ dim.global_size[0] * dim.global_size[1],
+ (char*)use_queues_flags.device_pointer,
+ (uint*)work_pool_wgs.device_pointer,
+ rtile.num_samples,
+ (float*)rtile.buffer);
+ }
+ }
+
+ return true;
+}
+
+SplitKernelFunction* CPUSplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
+{
+ CPUSplitKernelFunction *kernel = new CPUSplitKernelFunction(device);
+
+ kernel->func = device->get_kernel_function<void(*)(KernelGlobals*, KernelData*)>(kernel_name);
+ if(!kernel->func) {
+ delete kernel;
+ return NULL;
+ }
+
+ return kernel;
+}
+
+int2 CPUSplitKernel::split_kernel_local_size()
+{
+ return make_int2(1, 1);
+}
+
+int2 CPUSplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memory& /*data*/, DeviceTask * /*task*/) {
+ return make_int2(64, 1);
+}
+
+uint64_t CPUSplitKernel::state_buffer_size(device_memory& kernel_globals, device_memory& /*data*/, size_t num_threads) {
+ KernelGlobals *kg = (KernelGlobals*)kernel_globals.device_pointer;
+
+ return split_data_buffer_size(kg, num_threads);
+}
+
+unordered_map<string, void*> CPUDevice::kernel_functions;
+
Device *device_cpu_create(DeviceInfo& info, Stats &stats, bool background)
{
return new CPUDevice(info, stats, background);
diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index dafac6dfcb3..606494f08ed 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -15,32 +15,36 @@
*/
#include <climits>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "device.h"
-#include "device_intern.h"
+#include "device/device.h"
+#include "device/device_intern.h"
+#include "device/device_split_kernel.h"
-#include "buffers.h"
+#include "render/buffers.h"
#ifdef WITH_CUDA_DYNLOAD
# include "cuew.h"
#else
-# include "util_opengl.h"
+# include "util/util_opengl.h"
# include <cuda.h>
# include <cudaGL.h>
#endif
-#include "util_debug.h"
-#include "util_logging.h"
-#include "util_map.h"
-#include "util_md5.h"
-#include "util_opengl.h"
-#include "util_path.h"
-#include "util_string.h"
-#include "util_system.h"
-#include "util_types.h"
-#include "util_time.h"
+#include "util/util_debug.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_md5.h"
+#include "util/util_opengl.h"
+#include "util/util_path.h"
+#include "util/util_string.h"
+#include "util/util_system.h"
+#include "util/util_types.h"
+#include "util/util_time.h"
+
+#include "kernel/split/kernel_split_data_types.h"
CCL_NAMESPACE_BEGIN
@@ -78,6 +82,31 @@ int cuewCompilerVersion(void)
} /* namespace */
#endif /* WITH_CUDA_DYNLOAD */
+class CUDADevice;
+
+class CUDASplitKernel : public DeviceSplitKernel {
+ CUDADevice *device;
+public:
+ explicit CUDASplitKernel(CUDADevice *device);
+
+ virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& kernel_globals,
+ device_memory& kernel_data_,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flag,
+ device_memory& work_pool_wgs);
+
+ virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&);
+ virtual int2 split_kernel_local_size();
+ virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task);
+};
+
class CUDADevice : public Device
{
public:
@@ -258,16 +287,21 @@ public:
return DebugFlags().cuda.adaptive_compile;
}
+ bool use_split_kernel()
+ {
+ return DebugFlags().cuda.split_kernel;
+ }
+
/* Common NVCC flags which stays the same regardless of shading model,
* kernel sources md5 and only depends on compiler or compilation settings.
*/
string compile_kernel_get_common_cflags(
- const DeviceRequestedFeatures& requested_features)
+ const DeviceRequestedFeatures& requested_features, bool split=false)
{
const int cuda_version = cuewCompilerVersion();
const int machine = system_cpu_bits();
- const string kernel_path = path_get("kernel");
- const string include = kernel_path;
+ const string source_path = path_get("source");
+ const string include_path = source_path;
string cflags = string_printf("-m%d "
"--ptxas-options=\"-v\" "
"--use_fast_math "
@@ -276,7 +310,7 @@ public:
"-I\"%s\"",
machine,
cuda_version,
- include.c_str());
+ include_path.c_str());
if(use_adaptive_compilation()) {
cflags += " " + requested_features.get_build_options();
}
@@ -287,6 +321,11 @@ public:
#ifdef WITH_CYCLES_DEBUG
cflags += " -D__KERNEL_DEBUG__";
#endif
+
+ if(split) {
+ cflags += " -D__SPLIT__";
+ }
+
return cflags;
}
@@ -306,21 +345,21 @@ public:
cuda_error_message("CUDA nvcc compiler version could not be parsed.");
return false;
}
- if(cuda_version < 75) {
+ if(cuda_version < 80) {
printf("Unsupported CUDA version %d.%d detected, "
- "you need CUDA 7.5 or newer.\n",
+ "you need CUDA 8.0 or newer.\n",
major, minor);
return false;
}
- else if(cuda_version != 75 && cuda_version != 80) {
+ else if(cuda_version != 80) {
printf("CUDA version %d.%d detected, build may succeed but only "
- "CUDA 7.5 and 8.0 are officially supported.\n",
+ "CUDA 8.0 is officially supported.\n",
major, minor);
}
return true;
}
- string compile_kernel(const DeviceRequestedFeatures& requested_features)
+ string compile_kernel(const DeviceRequestedFeatures& requested_features, bool split=false)
{
/* Compute cubin name. */
int major, minor;
@@ -329,7 +368,8 @@ public:
/* Attempt to use kernel provided with Blender. */
if(!use_adaptive_compilation()) {
- const string cubin = path_get(string_printf("lib/kernel_sm_%d%d.cubin",
+ const string cubin = path_get(string_printf(split ? "lib/kernel_split_sm_%d%d.cubin"
+ : "lib/kernel_sm_%d%d.cubin",
major, minor));
VLOG(1) << "Testing for pre-compiled kernel " << cubin << ".";
if(path_exists(cubin)) {
@@ -339,18 +379,19 @@ public:
}
const string common_cflags =
- compile_kernel_get_common_cflags(requested_features);
+ compile_kernel_get_common_cflags(requested_features, split);
/* Try to use locally compiled kernel. */
- const string kernel_path = path_get("kernel");
- const string kernel_md5 = path_files_md5_hash(kernel_path);
+ const string source_path = path_get("source");
+ const string kernel_md5 = path_files_md5_hash(source_path);
/* We include cflags into md5 so changing cuda toolkit or changing other
* compiler command line arguments makes sure cubin gets re-built.
*/
const string cubin_md5 = util_md5_string(kernel_md5 + common_cflags);
- const string cubin_file = string_printf("cycles_kernel_sm%d%d_%s.cubin",
+ const string cubin_file = string_printf(split ? "cycles_kernel_split_sm%d%d_%s.cubin"
+ : "cycles_kernel_sm%d%d_%s.cubin",
major, minor,
cubin_md5.c_str());
const string cubin = path_cache_get(path_join("kernels", cubin_file));
@@ -383,9 +424,10 @@ public:
return "";
}
const char *nvcc = cuewCompilerPath();
- const string kernel = path_join(kernel_path,
- path_join("kernels",
- path_join("cuda", "kernel.cu")));
+ const string kernel = path_join(
+ path_join(source_path, "kernel"),
+ path_join("kernels",
+ path_join("cuda", split ? "kernel_split.cu" : "kernel.cu")));
double starttime = time_dt();
printf("Compiling CUDA kernel ...\n");
@@ -433,7 +475,7 @@ public:
return false;
/* get kernel */
- string cubin = compile_kernel(requested_features);
+ string cubin = compile_kernel(requested_features, use_split_kernel());
if(cubin == "")
return false;
@@ -466,8 +508,14 @@ public:
}
}
- void mem_alloc(device_memory& mem, MemoryType /*type*/)
+ void mem_alloc(const char *name, device_memory& mem, MemoryType /*type*/)
{
+ if(name) {
+ VLOG(1) << "Buffer allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
cuda_push_context();
CUdeviceptr device_pointer;
size_t size = mem.memory_size();
@@ -504,7 +552,9 @@ public:
void mem_zero(device_memory& mem)
{
- memset((void*)mem.data_pointer, 0, mem.memory_size());
+ if(mem.data_pointer) {
+ memset((void*)mem.data_pointer, 0, mem.memory_size());
+ }
cuda_push_context();
if(mem.device_pointer)
@@ -617,7 +667,7 @@ public:
/* Data Storage */
if(interpolation == INTERPOLATION_NONE) {
if(has_bindless_textures) {
- mem_alloc(mem, MEM_READ_ONLY);
+ mem_alloc(NULL, mem, MEM_READ_ONLY);
mem_copy_to(mem);
cuda_push_context();
@@ -641,7 +691,7 @@ public:
cuda_pop_context();
}
else {
- mem_alloc(mem, MEM_READ_ONLY);
+ mem_alloc(NULL, mem, MEM_READ_ONLY);
mem_copy_to(mem);
cuda_push_context();
@@ -1258,25 +1308,48 @@ public:
/* Upload Bindless Mapping */
load_bindless_mapping();
- /* keep rendering tiles until done */
- while(task->acquire_tile(this, tile)) {
- int start_sample = tile.start_sample;
- int end_sample = tile.start_sample + tile.num_samples;
+ if(!use_split_kernel()) {
+ /* keep rendering tiles until done */
+ while(task->acquire_tile(this, tile)) {
+ int start_sample = tile.start_sample;
+ int end_sample = tile.start_sample + tile.num_samples;
- for(int sample = start_sample; sample < end_sample; sample++) {
- if(task->get_cancel()) {
- if(task->need_finish_queue == false)
- break;
- }
+ for(int sample = start_sample; sample < end_sample; sample++) {
+ if(task->get_cancel()) {
+ if(task->need_finish_queue == false)
+ break;
+ }
- path_trace(tile, sample, branched);
+ path_trace(tile, sample, branched);
- tile.sample = sample + 1;
+ tile.sample = sample + 1;
- task->update_progress(&tile, tile.w*tile.h);
+ task->update_progress(&tile, tile.w*tile.h);
+ }
+
+ task->release_tile(tile);
+ }
+ }
+ else {
+ DeviceRequestedFeatures requested_features;
+ if(!use_adaptive_compilation()) {
+ requested_features.max_closure = 64;
}
- task->release_tile(tile);
+ CUDASplitKernel split_kernel(this);
+ split_kernel.load_kernels(requested_features);
+
+ while(task->acquire_tile(this, tile)) {
+ device_memory void_buffer;
+ split_kernel.path_trace(task, tile, void_buffer, void_buffer);
+
+ task->release_tile(tile);
+
+ if(task->get_cancel()) {
+ if(task->need_finish_queue == false)
+ break;
+ }
+ }
}
}
else if(task->type == DeviceTask::SHADER) {
@@ -1329,8 +1402,223 @@ public:
{
task_pool.cancel();
}
+
+ friend class CUDASplitKernelFunction;
+ friend class CUDASplitKernel;
+};
+
+/* redefine the cuda_assert macro so it can be used outside of the CUDADevice class
+ * now that the definition of that class is complete
+ */
+#undef cuda_assert
+#define cuda_assert(stmt) \
+ { \
+ CUresult result = stmt; \
+ \
+ if(result != CUDA_SUCCESS) { \
+ string message = string_printf("CUDA error: %s in %s", cuewErrorString(result), #stmt); \
+ if(device->error_msg == "") \
+ device->error_msg = message; \
+ fprintf(stderr, "%s\n", message.c_str()); \
+ /*cuda_abort();*/ \
+ device->cuda_error_documentation(); \
+ } \
+ } (void)0
+
+/* split kernel */
+
+class CUDASplitKernelFunction : public SplitKernelFunction{
+ CUDADevice* device;
+ CUfunction func;
+public:
+ CUDASplitKernelFunction(CUDADevice *device, CUfunction func) : device(device), func(func) {}
+
+ /* enqueue the kernel, returns false if there is an error */
+ bool enqueue(const KernelDimensions &dim, device_memory &/*kg*/, device_memory &/*data*/)
+ {
+ return enqueue(dim, NULL);
+ }
+
+ /* enqueue the kernel, returns false if there is an error */
+ bool enqueue(const KernelDimensions &dim, void *args[])
+ {
+ device->cuda_push_context();
+
+ if(device->have_error())
+ return false;
+
+ /* we ignore dim.local_size for now, as this is faster */
+ int threads_per_block;
+ cuda_assert(cuFuncGetAttribute(&threads_per_block, CU_FUNC_ATTRIBUTE_MAX_THREADS_PER_BLOCK, func));
+
+ int xthreads = (int)sqrt(threads_per_block);
+ int ythreads = (int)sqrt(threads_per_block);
+
+ int xblocks = (dim.global_size[0] + xthreads - 1)/xthreads;
+ int yblocks = (dim.global_size[1] + ythreads - 1)/ythreads;
+
+ cuda_assert(cuFuncSetCacheConfig(func, CU_FUNC_CACHE_PREFER_L1));
+
+ cuda_assert(cuLaunchKernel(func,
+ xblocks , yblocks, 1, /* blocks */
+ xthreads, ythreads, 1, /* threads */
+ 0, 0, args, 0));
+
+ device->cuda_pop_context();
+
+ return !device->have_error();
+ }
};
+CUDASplitKernel::CUDASplitKernel(CUDADevice *device) : DeviceSplitKernel(device), device(device)
+{
+}
+
+uint64_t CUDASplitKernel::state_buffer_size(device_memory& /*kg*/, device_memory& /*data*/, size_t num_threads)
+{
+ device_vector<uint64_t> size_buffer;
+ size_buffer.resize(1);
+ device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
+
+ device->cuda_push_context();
+
+ uint threads = num_threads;
+ CUdeviceptr d_size = device->cuda_device_ptr(size_buffer.device_pointer);
+
+ struct args_t {
+ uint* num_threads;
+ CUdeviceptr* size;
+ };
+
+ args_t args = {
+ &threads,
+ &d_size
+ };
+
+ CUfunction state_buffer_size;
+ cuda_assert(cuModuleGetFunction(&state_buffer_size, device->cuModule, "kernel_cuda_state_buffer_size"));
+
+ cuda_assert(cuLaunchKernel(state_buffer_size,
+ 1, 1, 1,
+ 1, 1, 1,
+ 0, 0, (void**)&args, 0));
+
+ device->cuda_pop_context();
+
+ device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
+ device->mem_free(size_buffer);
+
+ return *size_buffer.get_data();
+}
+
+bool CUDASplitKernel::enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& /*kernel_globals*/,
+ device_memory& /*kernel_data*/,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flag,
+ device_memory& work_pool_wgs)
+{
+ device->cuda_push_context();
+
+ CUdeviceptr d_split_data = device->cuda_device_ptr(split_data.device_pointer);
+ CUdeviceptr d_ray_state = device->cuda_device_ptr(ray_state.device_pointer);
+ CUdeviceptr d_queue_index = device->cuda_device_ptr(queue_index.device_pointer);
+ CUdeviceptr d_use_queues_flag = device->cuda_device_ptr(use_queues_flag.device_pointer);
+ CUdeviceptr d_work_pool_wgs = device->cuda_device_ptr(work_pool_wgs.device_pointer);
+
+ CUdeviceptr d_rng_state = device->cuda_device_ptr(rtile.rng_state);
+ CUdeviceptr d_buffer = device->cuda_device_ptr(rtile.buffer);
+
+ int end_sample = rtile.start_sample + rtile.num_samples;
+ int queue_size = dim.global_size[0] * dim.global_size[1];
+
+ struct args_t {
+ CUdeviceptr* split_data_buffer;
+ int* num_elements;
+ CUdeviceptr* ray_state;
+ CUdeviceptr* rng_state;
+ int* start_sample;
+ int* end_sample;
+ int* sx;
+ int* sy;
+ int* sw;
+ int* sh;
+ int* offset;
+ int* stride;
+ CUdeviceptr* queue_index;
+ int* queuesize;
+ CUdeviceptr* use_queues_flag;
+ CUdeviceptr* work_pool_wgs;
+ int* num_samples;
+ CUdeviceptr* buffer;
+ };
+
+ args_t args = {
+ &d_split_data,
+ &num_global_elements,
+ &d_ray_state,
+ &d_rng_state,
+ &rtile.start_sample,
+ &end_sample,
+ &rtile.x,
+ &rtile.y,
+ &rtile.w,
+ &rtile.h,
+ &rtile.offset,
+ &rtile.stride,
+ &d_queue_index,
+ &queue_size,
+ &d_use_queues_flag,
+ &d_work_pool_wgs,
+ &rtile.num_samples,
+ &d_buffer
+ };
+
+ CUfunction data_init;
+ cuda_assert(cuModuleGetFunction(&data_init, device->cuModule, "kernel_cuda_path_trace_data_init"));
+ if(device->have_error()) {
+ return false;
+ }
+
+ CUDASplitKernelFunction(device, data_init).enqueue(dim, (void**)&args);
+
+ device->cuda_pop_context();
+
+ return !device->have_error();
+}
+
+SplitKernelFunction* CUDASplitKernel::get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&)
+{
+ CUfunction func;
+
+ device->cuda_push_context();
+
+ cuda_assert(cuModuleGetFunction(&func, device->cuModule, (string("kernel_cuda_") + kernel_name).data()));
+ if(device->have_error()) {
+ device->cuda_error_message(string_printf("kernel \"kernel_cuda_%s\" not found in module", kernel_name.data()));
+ return NULL;
+ }
+
+ device->cuda_pop_context();
+
+ return new CUDASplitKernelFunction(device, func);
+}
+
+int2 CUDASplitKernel::split_kernel_local_size()
+{
+ return make_int2(32, 1);
+}
+
+int2 CUDASplitKernel::split_kernel_global_size(device_memory& /*kg*/, device_memory& /*data*/, DeviceTask */*task*/)
+{
+ /* TODO(mai): implement something here to detect ideal work size */
+ return make_int2(256, 256);
+}
+
bool device_cuda_init(void)
{
#ifdef WITH_CUDA_DYNLOAD
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 5b5b4dc6802..4b10514a9d2 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -28,10 +28,10 @@
* other devices this is a pointer to device memory, where we will copy memory
* to and from. */
-#include "util_debug.h"
-#include "util_half.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_debug.h"
+#include "util/util_half.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -48,7 +48,8 @@ enum DataType {
TYPE_UINT,
TYPE_INT,
TYPE_FLOAT,
- TYPE_HALF
+ TYPE_HALF,
+ TYPE_UINT64,
};
static inline size_t datatype_size(DataType datatype)
@@ -59,6 +60,7 @@ static inline size_t datatype_size(DataType datatype)
case TYPE_UINT: return sizeof(uint);
case TYPE_INT: return sizeof(int);
case TYPE_HALF: return sizeof(half);
+ case TYPE_UINT64: return sizeof(uint64_t);
default: return 0;
}
}
@@ -160,6 +162,11 @@ template<> struct device_type_traits<half4> {
static const int num_elements = 4;
};
+template<> struct device_type_traits<uint64_t> {
+ static const DataType data_type = TYPE_UINT64;
+ static const int num_elements = 1;
+};
+
/* Device Memory */
class device_memory
@@ -180,10 +187,27 @@ public:
/* device pointer */
device_ptr device_pointer;
-protected:
- device_memory() {}
+ device_memory()
+ {
+ data_type = device_type_traits<uchar>::data_type;
+ data_elements = device_type_traits<uchar>::num_elements;
+ data_pointer = 0;
+ data_size = 0;
+ device_size = 0;
+ data_width = 0;
+ data_height = 0;
+ data_depth = 0;
+ device_pointer = 0;
+ }
virtual ~device_memory() { assert(!device_pointer); }
+ void resize(size_t size)
+ {
+ data_size = size;
+ data_width = size;
+ }
+
+protected:
/* no copying */
device_memory(const device_memory&);
device_memory& operator = (const device_memory&);
@@ -198,16 +222,8 @@ public:
{
data_type = device_type_traits<T>::data_type;
data_elements = device_type_traits<T>::num_elements;
- data_pointer = 0;
- data_size = 0;
- device_size = 0;
- data_width = 0;
- data_height = 0;
- data_depth = 0;
assert(data_elements > 0);
-
- device_pointer = 0;
}
virtual ~device_vector() {}
@@ -266,6 +282,7 @@ public:
data_height = 0;
data_depth = 0;
data_size = 0;
+ device_pointer = 0;
}
size_t size()
diff --git a/intern/cycles/device/device_multi.cpp b/intern/cycles/device/device_multi.cpp
index 31b800640d3..624260a81c8 100644
--- a/intern/cycles/device/device_multi.cpp
+++ b/intern/cycles/device/device_multi.cpp
@@ -17,17 +17,17 @@
#include <stdlib.h>
#include <sstream>
-#include "device.h"
-#include "device_intern.h"
-#include "device_network.h"
+#include "device/device.h"
+#include "device/device_intern.h"
+#include "device/device_network.h"
-#include "buffers.h"
+#include "render/buffers.h"
-#include "util_foreach.h"
-#include "util_list.h"
-#include "util_logging.h"
-#include "util_map.h"
-#include "util_time.h"
+#include "util/util_foreach.h"
+#include "util/util_list.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
@@ -106,11 +106,11 @@ public:
return true;
}
- void mem_alloc(device_memory& mem, MemoryType type)
+ void mem_alloc(const char *name, device_memory& mem, MemoryType type)
{
foreach(SubDevice& sub, devices) {
mem.device_pointer = 0;
- sub.device->mem_alloc(mem, type);
+ sub.device->mem_alloc(name, mem, type);
sub.ptr_map[unique_ptr] = mem.device_pointer;
}
@@ -162,6 +162,7 @@ public:
void mem_free(device_memory& mem)
{
device_ptr tmp = mem.device_pointer;
+ stats.mem_free(mem.device_size);
foreach(SubDevice& sub, devices) {
mem.device_pointer = sub.ptr_map[tmp];
@@ -170,7 +171,6 @@ public:
}
mem.device_pointer = 0;
- stats.mem_free(mem.device_size);
}
void const_copy_to(const char *name, void *host, size_t size)
@@ -202,6 +202,7 @@ public:
void tex_free(device_memory& mem)
{
device_ptr tmp = mem.device_pointer;
+ stats.mem_free(mem.device_size);
foreach(SubDevice& sub, devices) {
mem.device_pointer = sub.ptr_map[tmp];
@@ -210,7 +211,6 @@ public:
}
mem.device_pointer = 0;
- stats.mem_free(mem.device_size);
}
void pixels_alloc(device_memory& mem)
diff --git a/intern/cycles/device/device_network.cpp b/intern/cycles/device/device_network.cpp
index 53eef6cf199..66758954f44 100644
--- a/intern/cycles/device/device_network.cpp
+++ b/intern/cycles/device/device_network.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "device.h"
-#include "device_intern.h"
-#include "device_network.h"
+#include "device/device.h"
+#include "device/device_intern.h"
+#include "device/device_network.h"
-#include "util_foreach.h"
-#include "util_logging.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
#if defined(WITH_NETWORK)
@@ -87,8 +87,14 @@ public:
snd.write();
}
- void mem_alloc(device_memory& mem, MemoryType type)
+ void mem_alloc(const char *name, device_memory& mem, MemoryType type)
{
+ if(name) {
+ VLOG(1) << "Buffer allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
thread_scoped_lock lock(rpc_lock);
mem.device_pointer = ++mem_counter;
@@ -481,7 +487,7 @@ protected:
mem.data_pointer = 0;
/* perform the allocation on the actual device */
- device->mem_alloc(mem, type);
+ device->mem_alloc(NULL, mem, type);
/* store a mapping to/from client_pointer and real device pointer */
pointer_mapping_insert(client_pointer, mem.device_pointer);
diff --git a/intern/cycles/device/device_network.h b/intern/cycles/device/device_network.h
index d28cfe3121f..a5d24c66018 100644
--- a/intern/cycles/device/device_network.h
+++ b/intern/cycles/device/device_network.h
@@ -33,12 +33,12 @@
#include <sstream>
#include <deque>
-#include "buffers.h"
+#include "render/buffers.h"
-#include "util_foreach.h"
-#include "util_list.h"
-#include "util_map.h"
-#include "util_string.h"
+#include "util/util_foreach.h"
+#include "util/util_list.h"
+#include "util/util_map.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/device/device_opencl.cpp b/intern/cycles/device/device_opencl.cpp
index ba94c592a5f..edd2047debc 100644
--- a/intern/cycles/device/device_opencl.cpp
+++ b/intern/cycles/device/device_opencl.cpp
@@ -16,12 +16,12 @@
#ifdef WITH_OPENCL
-#include "opencl/opencl.h"
+#include "device/opencl/opencl.h"
-#include "device_intern.h"
+#include "device/device_intern.h"
-#include "util_foreach.h"
-#include "util_logging.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/device/device_split_kernel.cpp b/intern/cycles/device/device_split_kernel.cpp
new file mode 100644
index 00000000000..ae462a560b7
--- /dev/null
+++ b/intern/cycles/device/device_split_kernel.cpp
@@ -0,0 +1,306 @@
+/*
+ * 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 "device/device_split_kernel.h"
+
+#include "kernel/kernel_types.h"
+#include "kernel/split/kernel_split_data_types.h"
+
+#include "util/util_time.h"
+
+CCL_NAMESPACE_BEGIN
+
+static const double alpha = 0.1; /* alpha for rolling average */
+
+DeviceSplitKernel::DeviceSplitKernel(Device *device) : device(device)
+{
+ current_max_closure = -1;
+ first_tile = true;
+
+ avg_time_per_sample = 0.0;
+
+ kernel_path_init = NULL;
+ kernel_scene_intersect = NULL;
+ kernel_lamp_emission = NULL;
+ kernel_do_volume = NULL;
+ kernel_queue_enqueue = NULL;
+ kernel_indirect_background = NULL;
+ kernel_shader_eval = NULL;
+ kernel_holdout_emission_blurring_pathtermination_ao = NULL;
+ kernel_subsurface_scatter = NULL;
+ kernel_direct_lighting = NULL;
+ kernel_shadow_blocked_ao = NULL;
+ kernel_shadow_blocked_dl = NULL;
+ kernel_next_iteration_setup = NULL;
+ kernel_indirect_subsurface = NULL;
+ kernel_buffer_update = NULL;
+}
+
+DeviceSplitKernel::~DeviceSplitKernel()
+{
+ device->mem_free(split_data);
+ device->mem_free(ray_state);
+ device->mem_free(use_queues_flag);
+ device->mem_free(queue_index);
+ device->mem_free(work_pool_wgs);
+
+ delete kernel_path_init;
+ delete kernel_scene_intersect;
+ delete kernel_lamp_emission;
+ delete kernel_do_volume;
+ delete kernel_queue_enqueue;
+ delete kernel_indirect_background;
+ delete kernel_shader_eval;
+ delete kernel_holdout_emission_blurring_pathtermination_ao;
+ delete kernel_subsurface_scatter;
+ delete kernel_direct_lighting;
+ delete kernel_shadow_blocked_ao;
+ delete kernel_shadow_blocked_dl;
+ delete kernel_next_iteration_setup;
+ delete kernel_indirect_subsurface;
+ delete kernel_buffer_update;
+}
+
+bool DeviceSplitKernel::load_kernels(const DeviceRequestedFeatures& requested_features)
+{
+#define LOAD_KERNEL(name) \
+ kernel_##name = get_split_kernel_function(#name, requested_features); \
+ if(!kernel_##name) { \
+ return false; \
+ }
+
+ LOAD_KERNEL(path_init);
+ LOAD_KERNEL(scene_intersect);
+ LOAD_KERNEL(lamp_emission);
+ LOAD_KERNEL(do_volume);
+ LOAD_KERNEL(queue_enqueue);
+ LOAD_KERNEL(indirect_background);
+ LOAD_KERNEL(shader_eval);
+ LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
+ LOAD_KERNEL(subsurface_scatter);
+ LOAD_KERNEL(direct_lighting);
+ LOAD_KERNEL(shadow_blocked_ao);
+ LOAD_KERNEL(shadow_blocked_dl);
+ LOAD_KERNEL(next_iteration_setup);
+ LOAD_KERNEL(indirect_subsurface);
+ LOAD_KERNEL(buffer_update);
+
+#undef LOAD_KERNEL
+
+ current_max_closure = requested_features.max_closure;
+
+ return true;
+}
+
+size_t DeviceSplitKernel::max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size)
+{
+ uint64_t size_per_element = state_buffer_size(kg, data, 1024) / 1024;
+ return max_buffer_size / size_per_element;
+}
+
+bool DeviceSplitKernel::path_trace(DeviceTask *task,
+ RenderTile& tile,
+ device_memory& kgbuffer,
+ device_memory& kernel_data)
+{
+ if(device->have_error()) {
+ return false;
+ }
+
+ /* Get local size */
+ size_t local_size[2];
+ {
+ int2 lsize = split_kernel_local_size();
+ local_size[0] = lsize[0];
+ local_size[1] = lsize[1];
+ }
+
+ /* Set gloabl size */
+ size_t global_size[2];
+ {
+ int2 gsize = split_kernel_global_size(kgbuffer, kernel_data, task);
+
+ /* Make sure that set work size is a multiple of local
+ * work size dimensions.
+ */
+ global_size[0] = round_up(gsize[0], local_size[0]);
+ global_size[1] = round_up(gsize[1], local_size[1]);
+ }
+
+ /* Number of elements in the global state buffer */
+ int num_global_elements = global_size[0] * global_size[1];
+ assert(num_global_elements % WORK_POOL_SIZE == 0);
+
+ /* Allocate all required global memory once. */
+ if(first_tile) {
+ first_tile = false;
+
+ /* Calculate max groups */
+
+ /* Denotes the maximum work groups possible w.r.t. current requested tile size. */
+ unsigned int max_work_groups = num_global_elements / WORK_POOL_SIZE + 1;
+
+ /* Allocate work_pool_wgs memory. */
+ work_pool_wgs.resize(max_work_groups * sizeof(unsigned int));
+ device->mem_alloc("work_pool_wgs", work_pool_wgs, MEM_READ_WRITE);
+
+ queue_index.resize(NUM_QUEUES * sizeof(int));
+ device->mem_alloc("queue_index", queue_index, MEM_READ_WRITE);
+
+ use_queues_flag.resize(sizeof(char));
+ device->mem_alloc("use_queues_flag", use_queues_flag, MEM_READ_WRITE);
+
+ ray_state.resize(num_global_elements);
+ device->mem_alloc("ray_state", ray_state, MEM_READ_WRITE);
+
+ split_data.resize(state_buffer_size(kgbuffer, kernel_data, num_global_elements));
+ device->mem_alloc("split_data", split_data, MEM_READ_WRITE);
+ }
+
+#define ENQUEUE_SPLIT_KERNEL(name, global_size, local_size) \
+ if(device->have_error()) { \
+ return false; \
+ } \
+ if(!kernel_##name->enqueue(KernelDimensions(global_size, local_size), kgbuffer, kernel_data)) { \
+ return false; \
+ }
+
+ tile.sample = tile.start_sample;
+
+ /* for exponential increase between tile updates */
+ int time_multiplier = 1;
+
+ while(tile.sample < tile.start_sample + tile.num_samples) {
+ /* to keep track of how long it takes to run a number of samples */
+ double start_time = time_dt();
+
+ /* initial guess to start rolling average */
+ const int initial_num_samples = 1;
+ /* approx number of samples per second */
+ int samples_per_second = (avg_time_per_sample > 0.0) ?
+ int(double(time_multiplier) / avg_time_per_sample) + 1 : initial_num_samples;
+
+ RenderTile subtile = tile;
+ subtile.start_sample = tile.sample;
+ subtile.num_samples = min(samples_per_second, tile.start_sample + tile.num_samples - tile.sample);
+
+ if(device->have_error()) {
+ return false;
+ }
+
+ /* reset state memory here as global size for data_init
+ * kernel might not be large enough to do in kernel
+ */
+ device->mem_zero(work_pool_wgs);
+ device->mem_zero(split_data);
+ device->mem_zero(ray_state);
+
+ if(!enqueue_split_kernel_data_init(KernelDimensions(global_size, local_size),
+ subtile,
+ num_global_elements,
+ kgbuffer,
+ kernel_data,
+ split_data,
+ ray_state,
+ queue_index,
+ use_queues_flag,
+ work_pool_wgs))
+ {
+ return false;
+ }
+
+ ENQUEUE_SPLIT_KERNEL(path_init, global_size, local_size);
+
+ bool activeRaysAvailable = true;
+
+ while(activeRaysAvailable) {
+ /* Do path-iteration in host [Enqueue Path-iteration kernels. */
+ for(int PathIter = 0; PathIter < 16; PathIter++) {
+ ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(do_volume, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(indirect_background, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(subsurface_scatter, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(shadow_blocked_ao, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(shadow_blocked_dl, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(indirect_subsurface, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
+ ENQUEUE_SPLIT_KERNEL(buffer_update, global_size, local_size);
+
+ if(task->get_cancel()) {
+ return true;
+ }
+ }
+
+ /* Decide if we should exit path-iteration in host. */
+ device->mem_copy_from(ray_state, 0, global_size[0] * global_size[1] * sizeof(char), 1, 1);
+
+ activeRaysAvailable = false;
+
+ for(int rayStateIter = 0; rayStateIter < global_size[0] * global_size[1]; ++rayStateIter) {
+ int8_t state = ray_state.get_data()[rayStateIter];
+
+ if(state != RAY_INACTIVE) {
+ if(state == RAY_INVALID) {
+ /* Something went wrong, abort to avoid looping endlessly. */
+ device->set_error("Split kernel error: invalid ray state");
+ return false;
+ }
+
+ /* Not all rays are RAY_INACTIVE. */
+ activeRaysAvailable = true;
+ break;
+ }
+ }
+
+ if(task->get_cancel()) {
+ return true;
+ }
+ }
+
+ double time_per_sample = ((time_dt()-start_time) / subtile.num_samples);
+
+ if(avg_time_per_sample == 0.0) {
+ /* start rolling average */
+ avg_time_per_sample = time_per_sample;
+ }
+ else {
+ avg_time_per_sample = alpha*time_per_sample + (1.0-alpha)*avg_time_per_sample;
+ }
+
+#undef ENQUEUE_SPLIT_KERNEL
+
+ tile.sample += subtile.num_samples;
+ task->update_progress(&tile, tile.w*tile.h*subtile.num_samples);
+
+ time_multiplier = min(time_multiplier << 1, 10);
+
+ if(task->get_cancel()) {
+ return true;
+ }
+ }
+
+ return true;
+}
+
+CCL_NAMESPACE_END
+
+
diff --git a/intern/cycles/device/device_split_kernel.h b/intern/cycles/device/device_split_kernel.h
new file mode 100644
index 00000000000..15a94953a11
--- /dev/null
+++ b/intern/cycles/device/device_split_kernel.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __DEVICE_SPLIT_KERNEL_H__
+#define __DEVICE_SPLIT_KERNEL_H__
+
+#include "device/device.h"
+#include "render/buffers.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* When allocate global memory in chunks. We may not be able to
+ * allocate exactly "CL_DEVICE_MAX_MEM_ALLOC_SIZE" bytes in chunks;
+ * Since some bytes may be needed for aligning chunks of memory;
+ * This is the amount of memory that we dedicate for that purpose.
+ */
+#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
+
+/* Types used for split kernel */
+
+class KernelDimensions {
+public:
+ size_t global_size[2];
+ size_t local_size[2];
+
+ KernelDimensions(size_t global_size_[2], size_t local_size_[2])
+ {
+ memcpy(global_size, global_size_, sizeof(global_size));
+ memcpy(local_size, local_size_, sizeof(local_size));
+ }
+};
+
+class SplitKernelFunction {
+public:
+ virtual ~SplitKernelFunction() {}
+
+ /* enqueue the kernel, returns false if there is an error */
+ virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data) = 0;
+};
+
+class DeviceSplitKernel {
+private:
+ Device *device;
+
+ SplitKernelFunction *kernel_path_init;
+ SplitKernelFunction *kernel_scene_intersect;
+ SplitKernelFunction *kernel_lamp_emission;
+ SplitKernelFunction *kernel_do_volume;
+ SplitKernelFunction *kernel_queue_enqueue;
+ SplitKernelFunction *kernel_indirect_background;
+ SplitKernelFunction *kernel_shader_eval;
+ SplitKernelFunction *kernel_holdout_emission_blurring_pathtermination_ao;
+ SplitKernelFunction *kernel_subsurface_scatter;
+ SplitKernelFunction *kernel_direct_lighting;
+ SplitKernelFunction *kernel_shadow_blocked_ao;
+ SplitKernelFunction *kernel_shadow_blocked_dl;
+ SplitKernelFunction *kernel_next_iteration_setup;
+ SplitKernelFunction *kernel_indirect_subsurface;
+ SplitKernelFunction *kernel_buffer_update;
+
+ /* Global memory variables [porting]; These memory is used for
+ * co-operation between different kernels; Data written by one
+ * kernel will be available to another kernel via this global
+ * memory.
+ */
+ device_memory split_data;
+ device_vector<uchar> ray_state;
+ device_memory queue_index; /* Array of size num_queues * sizeof(int) that tracks the size of each queue. */
+
+ /* Flag to make sceneintersect and lampemission kernel use queues. */
+ device_memory use_queues_flag;
+
+ /* Approximate time it takes to complete one sample */
+ double avg_time_per_sample;
+
+ /* Work pool with respect to each work group. */
+ device_memory work_pool_wgs;
+
+ /* clos_max value for which the kernels have been loaded currently. */
+ int current_max_closure;
+
+ /* Marked True in constructor and marked false at the end of path_trace(). */
+ bool first_tile;
+
+public:
+ explicit DeviceSplitKernel(Device* device);
+ virtual ~DeviceSplitKernel();
+
+ bool load_kernels(const DeviceRequestedFeatures& requested_features);
+ bool path_trace(DeviceTask *task,
+ RenderTile& rtile,
+ device_memory& kgbuffer,
+ device_memory& kernel_data);
+
+ virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads) = 0;
+ size_t max_elements_for_max_buffer_size(device_memory& kg, device_memory& data, uint64_t max_buffer_size);
+
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& kernel_globals,
+ device_memory& kernel_data_,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flag,
+ device_memory& work_pool_wgs) = 0;
+
+ virtual SplitKernelFunction* get_split_kernel_function(string kernel_name, const DeviceRequestedFeatures&) = 0;
+ virtual int2 split_kernel_local_size() = 0;
+ virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask *task) = 0;
+};
+
+CCL_NAMESPACE_END
+
+#endif /* __DEVICE_SPLIT_KERNEL_H__ */
+
+
+
diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp
index 48d18035c13..ca303365627 100644
--- a/intern/cycles/device/device_task.cpp
+++ b/intern/cycles/device/device_task.cpp
@@ -17,12 +17,12 @@
#include <stdlib.h>
#include <string.h>
-#include "device_task.h"
+#include "device/device_task.h"
-#include "buffers.h"
+#include "render/buffers.h"
-#include "util_algorithm.h"
-#include "util_time.h"
+#include "util/util_algorithm.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h
index 8bd54c3d2b0..feee89fd6e4 100644
--- a/intern/cycles/device/device_task.h
+++ b/intern/cycles/device/device_task.h
@@ -17,11 +17,11 @@
#ifndef __DEVICE_TASK_H__
#define __DEVICE_TASK_H__
-#include "device_memory.h"
+#include "device/device_memory.h"
-#include "util_function.h"
-#include "util_list.h"
-#include "util_task.h"
+#include "util/util_function.h"
+#include "util/util_list.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -51,6 +51,8 @@ public:
int shader_filter;
int shader_x, shader_w;
+ int passes_size;
+
explicit DeviceTask(Type type = PATH_TRACE);
int get_subtask_count(int num, int max_size = 0);
diff --git a/intern/cycles/device/opencl/opencl.h b/intern/cycles/device/opencl/opencl.h
index 4023ba89a10..764216d0dfa 100644
--- a/intern/cycles/device/opencl/opencl.h
+++ b/intern/cycles/device/opencl/opencl.h
@@ -16,39 +16,39 @@
#ifdef WITH_OPENCL
-#include "device.h"
+#include "device/device.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_string.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_string.h"
#include "clew.h"
CCL_NAMESPACE_BEGIN
-#define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
-
-/* Macro declarations used with split kernel */
-
-/* Macro to enable/disable work-stealing */
-#define __WORK_STEALING__
-
-#define SPLIT_KERNEL_LOCAL_SIZE_X 64
-#define SPLIT_KERNEL_LOCAL_SIZE_Y 1
+/* Define CYCLES_DISABLE_DRIVER_WORKAROUNDS to disable workaounds for testing */
+#ifndef CYCLES_DISABLE_DRIVER_WORKAROUNDS
+/* Work around AMD driver hangs by ensuring each command is finished before doing anything else. */
+# undef clEnqueueNDRangeKernel
+# define clEnqueueNDRangeKernel(a, b, c, d, e, f, g, h, i) \
+ clFinish(a); \
+ CLEW_GET_FUN(__clewEnqueueNDRangeKernel)(a, b, c, d, e, f, g, h, i); \
+ clFinish(a);
+
+# undef clEnqueueWriteBuffer
+# define clEnqueueWriteBuffer(a, b, c, d, e, f, g, h, i) \
+ clFinish(a); \
+ CLEW_GET_FUN(__clewEnqueueWriteBuffer)(a, b, c, d, e, f, g, h, i); \
+ clFinish(a);
+
+# undef clEnqueueReadBuffer
+# define clEnqueueReadBuffer(a, b, c, d, e, f, g, h, i) \
+ clFinish(a); \
+ CLEW_GET_FUN(__clewEnqueueReadBuffer)(a, b, c, d, e, f, g, h, i); \
+ clFinish(a);
+#endif /* CYCLES_DISABLE_DRIVER_WORKAROUNDS */
-/* This value may be tuned according to the scene we are rendering.
- *
- * Modifying PATH_ITER_INC_FACTOR value proportional to number of expected
- * ray-bounces will improve performance.
- */
-#define PATH_ITER_INC_FACTOR 8
-
-/* When allocate global memory in chunks. We may not be able to
- * allocate exactly "CL_DEVICE_MAX_MEM_ALLOC_SIZE" bytes in chunks;
- * Since some bytes may be needed for aligning chunks of memory;
- * This is the amount of memory that we dedicate for that purpose.
- */
-#define DATA_ALLOCATION_MEM_FACTOR 5000000 //5MB
+#define CL_MEM_PTR(p) ((cl_mem)(uintptr_t)(p))
struct OpenCLPlatformDevice {
OpenCLPlatformDevice(cl_platform_id platform_id,
@@ -90,6 +90,54 @@ public:
cl_device_id device_id);
static void get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices,
bool force_all = false);
+ static bool use_single_program();
+
+ /* ** Some handy shortcuts to low level cl*GetInfo() functions. ** */
+
+ /* Platform information. */
+ static bool get_num_platforms(cl_uint *num_platforms, cl_int *error = NULL);
+ static cl_uint get_num_platforms();
+
+ static bool get_platforms(vector<cl_platform_id> *platform_ids,
+ cl_int *error = NULL);
+ static vector<cl_platform_id> get_platforms();
+
+ static bool get_platform_name(cl_platform_id platform_id,
+ string *platform_name);
+ static string get_platform_name(cl_platform_id platform_id);
+
+ static bool get_num_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ cl_uint *num_devices,
+ cl_int *error = NULL);
+ static cl_uint get_num_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type);
+
+ static bool get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ vector<cl_device_id> *device_ids,
+ cl_int* error = NULL);
+ static vector<cl_device_id> get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type);
+
+ /* Device information. */
+ static bool get_device_name(cl_device_id device_id,
+ string *device_name,
+ cl_int* error = NULL);
+
+ static string get_device_name(cl_device_id device_id);
+
+ static bool get_device_type(cl_device_id device_id,
+ cl_device_type *device_type,
+ cl_int* error = NULL);
+ static cl_device_type get_device_type(cl_device_id device_id);
+
+ /* Get somewhat more readable device name.
+ * Main difference is AMD OpenCL here which only gives code name
+ * for the regular device name. This will give more sane device
+ * name using some extensions.
+ */
+ static string get_readable_device_name(cl_device_id device_id);
};
/* Thread safe cache for contexts and programs.
@@ -248,6 +296,7 @@ public:
bool device_initialized;
string platform_name;
+ string device_name;
bool opencl_error(cl_int err);
void opencl_error(const string& message);
@@ -266,10 +315,10 @@ public:
/* Has to be implemented by the real device classes.
* The base device will then load all these programs. */
- virtual void load_kernels(const DeviceRequestedFeatures& requested_features,
+ virtual bool load_kernels(const DeviceRequestedFeatures& requested_features,
vector<OpenCLProgram*> &programs) = 0;
- void mem_alloc(device_memory& mem, MemoryType type);
+ void mem_alloc(const char *name, device_memory& mem, MemoryType type);
void mem_copy_to(device_memory& mem);
void mem_copy_from(device_memory& mem, int y, int w, int h, int elem);
void mem_zero(device_memory& mem);
@@ -326,16 +375,39 @@ protected:
class ArgumentWrapper {
public:
- ArgumentWrapper() : size(0), pointer(NULL) {}
- template <typename T>
+ ArgumentWrapper() : size(0), pointer(NULL)
+ {
+ }
+
+ ArgumentWrapper(device_memory& argument) : size(sizeof(void*)),
+ pointer((void*)(&argument.device_pointer))
+ {
+ }
+
+ template<typename T>
+ ArgumentWrapper(device_vector<T>& argument) : size(sizeof(void*)),
+ pointer((void*)(&argument.device_pointer))
+ {
+ }
+
+ template<typename T>
ArgumentWrapper(T& argument) : size(sizeof(argument)),
- pointer(&argument) { }
+ pointer(&argument)
+ {
+ }
+
ArgumentWrapper(int argument) : size(sizeof(int)),
int_value(argument),
- pointer(&int_value) { }
+ pointer(&int_value)
+ {
+ }
+
ArgumentWrapper(float argument) : size(sizeof(float)),
float_value(argument),
- pointer(&float_value) { }
+ pointer(&float_value)
+ {
+ }
+
size_t size;
int int_value;
float float_value;
diff --git a/intern/cycles/device/opencl/opencl_base.cpp b/intern/cycles/device/opencl/opencl_base.cpp
index a2b900312e7..52d0662a8e3 100644
--- a/intern/cycles/device/opencl/opencl_base.cpp
+++ b/intern/cycles/device/opencl/opencl_base.cpp
@@ -16,15 +16,15 @@
#ifdef WITH_OPENCL
-#include "opencl.h"
+#include "device/opencl/opencl.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_md5.h"
-#include "util_path.h"
-#include "util_time.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
@@ -82,9 +82,10 @@ OpenCLDeviceBase::OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool backgrou
cpPlatform = platform_device.platform_id;
cdDevice = platform_device.device_id;
platform_name = platform_device.platform_name;
+ device_name = platform_device.device_name;
VLOG(2) << "Creating new Cycles device for OpenCL platform "
<< platform_name << ", device "
- << platform_device.device_name << ".";
+ << device_name << ".";
{
/* try to use cached context */
@@ -113,12 +114,16 @@ OpenCLDeviceBase::OpenCLDeviceBase(DeviceInfo& info, Stats &stats, bool backgrou
}
cqCommandQueue = clCreateCommandQueue(cxContext, cdDevice, 0, &ciErr);
- if(opencl_error(ciErr))
+ if(opencl_error(ciErr)) {
+ opencl_error("OpenCL: Error creating command queue");
return;
+ }
null_mem = (device_ptr)clCreateBuffer(cxContext, CL_MEM_READ_ONLY, 1, NULL, &ciErr);
- if(opencl_error(ciErr))
+ if(opencl_error(ciErr)) {
+ opencl_error("OpenCL: Error creating memory buffer for NULL");
return;
+ }
fprintf(stderr, "Device init success\n");
device_initialized = true;
@@ -147,10 +152,8 @@ OpenCLDeviceBase::~OpenCLDeviceBase()
void CL_CALLBACK OpenCLDeviceBase::context_notify_callback(const char *err_info,
const void * /*private_info*/, size_t /*cb*/, void *user_data)
{
- char name[256];
- clGetDeviceInfo((cl_device_id)user_data, CL_DEVICE_NAME, sizeof(name), &name, NULL);
-
- fprintf(stderr, "OpenCL error (%s): %s\n", name, err_info);
+ string device_name = OpenCLInfo::get_device_name((cl_device_id)user_data);
+ fprintf(stderr, "OpenCL error (%s): %s\n", device_name.c_str(), err_info);
}
bool OpenCLDeviceBase::opencl_version_check()
@@ -191,6 +194,8 @@ string OpenCLDeviceBase::device_md5_hash(string kernel_custom_build_options)
bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_features)
{
+ VLOG(2) << "Loading kernels for platform " << platform_name
+ << ", device " << device_name << ".";
/* Verify if device was initialized. */
if(!device_initialized) {
fprintf(stderr, "OpenCL: failed to initialize device.\n");
@@ -206,11 +211,14 @@ bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_fea
base_program.add_kernel(ustring("convert_to_half_float"));
base_program.add_kernel(ustring("shader"));
base_program.add_kernel(ustring("bake"));
+ base_program.add_kernel(ustring("zero_buffer"));
vector<OpenCLProgram*> programs;
programs.push_back(&base_program);
/* Call actual class to fill the vector with its programs. */
- load_kernels(requested_features, programs);
+ if(!load_kernels(requested_features, programs)) {
+ return false;
+ }
/* Parallel compilation is supported by Cycles, but currently all OpenCL frameworks
* serialize the calls internally, so it's not much use right now.
@@ -242,8 +250,14 @@ bool OpenCLDeviceBase::load_kernels(const DeviceRequestedFeatures& requested_fea
return true;
}
-void OpenCLDeviceBase::mem_alloc(device_memory& mem, MemoryType type)
+void OpenCLDeviceBase::mem_alloc(const char *name, device_memory& mem, MemoryType type)
{
+ if(name) {
+ VLOG(1) << "Buffer allocate: " << name << ", "
+ << string_human_readable_number(mem.memory_size()) << " bytes. ("
+ << string_human_readable_size(mem.memory_size()) << ")";
+ }
+
size_t size = mem.memory_size();
cl_mem_flags mem_flag;
@@ -311,8 +325,61 @@ void OpenCLDeviceBase::mem_copy_from(device_memory& mem, int y, int w, int h, in
void OpenCLDeviceBase::mem_zero(device_memory& mem)
{
if(mem.device_pointer) {
- memset((void*)mem.data_pointer, 0, mem.memory_size());
- mem_copy_to(mem);
+ if(base_program.is_loaded()) {
+ cl_kernel ckZeroBuffer = base_program(ustring("zero_buffer"));
+
+ size_t global_size[] = {1024, 1024};
+ size_t num_threads = global_size[0] * global_size[1];
+
+ cl_mem d_buffer = CL_MEM_PTR(mem.device_pointer);
+ cl_ulong d_offset = 0;
+ cl_ulong d_size = 0;
+
+ while(d_offset < mem.memory_size()) {
+ d_size = std::min<cl_ulong>(num_threads*sizeof(float4), mem.memory_size() - d_offset);
+
+ kernel_set_args(ckZeroBuffer, 0, d_buffer, d_size, d_offset);
+
+ ciErr = clEnqueueNDRangeKernel(cqCommandQueue,
+ ckZeroBuffer,
+ 2,
+ NULL,
+ global_size,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ opencl_assert_err(ciErr, "clEnqueueNDRangeKernel");
+
+ d_offset += d_size;
+ }
+ }
+
+ if(mem.data_pointer) {
+ memset((void*)mem.data_pointer, 0, mem.memory_size());
+ }
+
+ if(!base_program.is_loaded()) {
+ void* zero = (void*)mem.data_pointer;
+
+ if(!mem.data_pointer) {
+ zero = util_aligned_malloc(mem.memory_size(), 16);
+ memset(zero, 0, mem.memory_size());
+ }
+
+ opencl_assert(clEnqueueWriteBuffer(cqCommandQueue,
+ CL_MEM_PTR(mem.device_pointer),
+ CL_TRUE,
+ 0,
+ mem.memory_size(),
+ zero,
+ 0,
+ NULL, NULL));
+
+ if(!mem.data_pointer) {
+ util_aligned_free(zero);
+ }
+ }
}
}
@@ -337,7 +404,7 @@ void OpenCLDeviceBase::const_copy_to(const char *name, void *host, size_t size)
device_vector<uchar> *data = new device_vector<uchar>();
data->copy((uchar*)host, size);
- mem_alloc(*data, MEM_READ_ONLY);
+ mem_alloc(name, *data, MEM_READ_ONLY);
i = const_mem_map.insert(ConstMemMap::value_type(name, data)).first;
}
else {
@@ -356,7 +423,7 @@ void OpenCLDeviceBase::tex_alloc(const char *name,
VLOG(1) << "Texture allocate: " << name << ", "
<< string_human_readable_number(mem.memory_size()) << " bytes. ("
<< string_human_readable_size(mem.memory_size()) << ")";
- mem_alloc(mem, MEM_READ_ONLY);
+ mem_alloc(NULL, mem, MEM_READ_ONLY);
mem_copy_to(mem);
assert(mem_map.find(name) == mem_map.end());
mem_map.insert(MemMap::value_type(name, mem.device_pointer));
@@ -460,7 +527,7 @@ void OpenCLDeviceBase::film_convert(DeviceTask& task, device_ptr buffer, device_
#define KERNEL_TEX(type, ttype, name) \
set_kernel_arg_mem(ckFilmConvertKernel, &start_arg_index, #name);
-#include "kernel_textures.h"
+#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
start_arg_index += kernel_set_args(ckFilmConvertKernel,
@@ -511,7 +578,7 @@ void OpenCLDeviceBase::shader(DeviceTask& task)
#define KERNEL_TEX(type, ttype, name) \
set_kernel_arg_mem(kernel, &start_arg_index, #name);
-#include "kernel_textures.h"
+#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
start_arg_index += kernel_set_args(kernel,
diff --git a/intern/cycles/device/opencl/opencl_mega.cpp b/intern/cycles/device/opencl/opencl_mega.cpp
index 6ea7619e022..a2fd1d71156 100644
--- a/intern/cycles/device/opencl/opencl_mega.cpp
+++ b/intern/cycles/device/opencl/opencl_mega.cpp
@@ -16,15 +16,15 @@
#ifdef WITH_OPENCL
-#include "opencl.h"
+#include "device/opencl/opencl.h"
-#include "buffers.h"
+#include "render/buffers.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "util_md5.h"
-#include "util_path.h"
-#include "util_time.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
@@ -43,11 +43,12 @@ public:
return true;
}
- virtual void load_kernels(const DeviceRequestedFeatures& /*requested_features*/,
+ virtual bool load_kernels(const DeviceRequestedFeatures& /*requested_features*/,
vector<OpenCLProgram*> &programs)
{
path_trace_program.add_kernel(ustring("path_trace"));
programs.push_back(&path_trace_program);
+ return true;
}
~OpenCLDeviceMegaKernel()
@@ -83,7 +84,7 @@ public:
#define KERNEL_TEX(type, ttype, name) \
set_kernel_arg_mem(ckPathTraceKernel, &start_arg_index, #name);
-#include "kernel_textures.h"
+#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
start_arg_index += kernel_set_args(ckPathTraceKernel,
diff --git a/intern/cycles/device/opencl/opencl_split.cpp b/intern/cycles/device/opencl/opencl_split.cpp
index 3c3c2150128..579dbc84f53 100644
--- a/intern/cycles/device/opencl/opencl_split.cpp
+++ b/intern/cycles/device/opencl/opencl_split.cpp
@@ -16,1290 +16,359 @@
#ifdef WITH_OPENCL
-#include "opencl.h"
+#include "device/opencl/opencl.h"
-#include "buffers.h"
+#include "render/buffers.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
+#include "kernel/split/kernel_split_data_types.h"
-#include "util_md5.h"
-#include "util_path.h"
-#include "util_time.h"
+#include "device/device_split_kernel.h"
+
+#include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
-/* TODO(sergey): This is to keep tile split on OpenCL level working
- * for now, since without this view-port render does not work as it
- * should.
- *
- * Ideally it'll be done on the higher level, but we need to get ready
- * for merge rather soon, so let's keep split logic private here in
- * the file.
- */
-class SplitRenderTile : public RenderTile {
-public:
- SplitRenderTile()
- : RenderTile(),
- buffer_offset_x(0),
- buffer_offset_y(0),
- rng_state_offset_x(0),
- rng_state_offset_y(0),
- buffer_rng_state_stride(0) {}
-
- explicit SplitRenderTile(RenderTile& tile)
- : RenderTile(),
- buffer_offset_x(0),
- buffer_offset_y(0),
- rng_state_offset_x(0),
- rng_state_offset_y(0),
- buffer_rng_state_stride(0)
- {
- x = tile.x;
- y = tile.y;
- w = tile.w;
- h = tile.h;
- start_sample = tile.start_sample;
- num_samples = tile.num_samples;
- sample = tile.sample;
- resolution = tile.resolution;
- offset = tile.offset;
- stride = tile.stride;
- buffer = tile.buffer;
- rng_state = tile.rng_state;
- buffers = tile.buffers;
+class OpenCLSplitKernel;
+
+static string get_build_options(OpenCLDeviceBase *device, const DeviceRequestedFeatures& requested_features)
+{
+ string build_options = "-D__SPLIT_KERNEL__ ";
+ build_options += requested_features.get_build_options();
+
+ /* Set compute device build option. */
+ cl_device_type device_type;
+ OpenCLInfo::get_device_type(device->cdDevice, &device_type, &device->ciErr);
+ assert(device->ciErr == CL_SUCCESS);
+ if(device_type == CL_DEVICE_TYPE_GPU) {
+ build_options += " -D__COMPUTE_DEVICE_GPU__";
}
- /* Split kernel is device global memory constrained;
- * hence split kernel cant render big tile size's in
- * one go. If the user sets a big tile size (big tile size
- * is a term relative to the available device global memory),
- * we split the tile further and then call path_trace on
- * each of those split tiles. The following variables declared,
- * assist in achieving that purpose
- */
- int buffer_offset_x;
- int buffer_offset_y;
- int rng_state_offset_x;
- int rng_state_offset_y;
- int buffer_rng_state_stride;
-};
+ return build_options;
+}
/* OpenCLDeviceSplitKernel's declaration/definition. */
class OpenCLDeviceSplitKernel : public OpenCLDeviceBase
{
public:
- /* Kernel declaration. */
+ DeviceSplitKernel *split_kernel;
OpenCLProgram program_data_init;
- OpenCLProgram program_scene_intersect;
- OpenCLProgram program_lamp_emission;
- OpenCLProgram program_queue_enqueue;
- OpenCLProgram program_background_buffer_update;
- OpenCLProgram program_shader_eval;
- OpenCLProgram program_holdout_emission_blurring_pathtermination_ao;
- OpenCLProgram program_direct_lighting;
- OpenCLProgram program_shadow_blocked;
- OpenCLProgram program_next_iteration_setup;
- OpenCLProgram program_sum_all_radiance;
-
- /* Global memory variables [porting]; These memory is used for
- * co-operation between different kernels; Data written by one
- * kernel will be available to another kernel via this global
- * memory.
- */
- cl_mem rng_coop;
- cl_mem throughput_coop;
- cl_mem L_transparent_coop;
- cl_mem PathRadiance_coop;
- cl_mem Ray_coop;
- cl_mem PathState_coop;
- cl_mem Intersection_coop;
- cl_mem kgbuffer; /* KernelGlobals buffer. */
-
- /* Global buffers for ShaderData. */
- cl_mem sd; /* ShaderData used in the main path-iteration loop. */
- cl_mem sd_DL_shadow; /* ShaderData used in Direct Lighting and
- * shadow_blocked kernel.
- */
-
- /* Global memory required for shadow blocked and accum_radiance. */
- cl_mem BSDFEval_coop;
- cl_mem ISLamp_coop;
- cl_mem LightRay_coop;
- cl_mem AOAlpha_coop;
- cl_mem AOBSDF_coop;
- cl_mem AOLightRay_coop;
- cl_mem Intersection_coop_shadow;
-
-#ifdef WITH_CYCLES_DEBUG
- /* DebugData memory */
- cl_mem debugdata_coop;
-#endif
-
- /* Global state array that tracks ray state. */
- cl_mem ray_state;
-
- /* Per sample buffers. */
- cl_mem per_sample_output_buffers;
-
- /* Denotes which sample each ray is being processed for. */
- cl_mem work_array;
-
- /* Queue */
- cl_mem Queue_data; /* Array of size queuesize * num_queues * sizeof(int). */
- cl_mem Queue_index; /* Array of size num_queues * sizeof(int);
- * Tracks the size of each queue.
- */
-
- /* Flag to make sceneintersect and lampemission kernel use queues. */
- cl_mem use_queues_flag;
-
- /* Amount of memory in output buffer associated with one pixel/thread. */
- size_t per_thread_output_buffer_size;
-
- /* Total allocatable available device memory. */
- size_t total_allocatable_memory;
-
- /* host version of ray_state; Used in checking host path-iteration
- * termination.
- */
- char *hostRayStateArray;
-
- /* Number of path-iterations to be done in one shot. */
- unsigned int PathIteration_times;
-
-#ifdef __WORK_STEALING__
- /* Work pool with respect to each work group. */
- cl_mem work_pool_wgs;
-
- /* Denotes the maximum work groups possible w.r.t. current tile size. */
- unsigned int max_work_groups;
-#endif
-
- /* clos_max value for which the kernels have been loaded currently. */
- int current_max_closure;
-
- /* Marked True in constructor and marked false at the end of path_trace(). */
- bool first_tile;
-
- OpenCLDeviceSplitKernel(DeviceInfo& info, Stats &stats, bool background_)
- : OpenCLDeviceBase(info, stats, background_)
- {
- background = background_;
-
- /* Initialize cl_mem variables. */
- kgbuffer = NULL;
- sd = NULL;
- sd_DL_shadow = NULL;
-
- rng_coop = NULL;
- throughput_coop = NULL;
- L_transparent_coop = NULL;
- PathRadiance_coop = NULL;
- Ray_coop = NULL;
- PathState_coop = NULL;
- Intersection_coop = NULL;
- ray_state = NULL;
-
- AOAlpha_coop = NULL;
- AOBSDF_coop = NULL;
- AOLightRay_coop = NULL;
- BSDFEval_coop = NULL;
- ISLamp_coop = NULL;
- LightRay_coop = NULL;
- Intersection_coop_shadow = NULL;
-
-#ifdef WITH_CYCLES_DEBUG
- debugdata_coop = NULL;
-#endif
-
- work_array = NULL;
-
- /* Queue. */
- Queue_data = NULL;
- Queue_index = NULL;
- use_queues_flag = NULL;
-
- per_sample_output_buffers = NULL;
-
- per_thread_output_buffer_size = 0;
- hostRayStateArray = NULL;
- PathIteration_times = PATH_ITER_INC_FACTOR;
-#ifdef __WORK_STEALING__
- work_pool_wgs = NULL;
- max_work_groups = 0;
-#endif
- current_max_closure = -1;
- first_tile = true;
-
- /* Get device's maximum memory that can be allocated. */
- ciErr = clGetDeviceInfo(cdDevice,
- CL_DEVICE_MAX_MEM_ALLOC_SIZE,
- sizeof(size_t),
- &total_allocatable_memory,
- NULL);
- assert(ciErr == CL_SUCCESS);
- if(platform_name == "AMD Accelerated Parallel Processing") {
- /* This value is tweak-able; AMD platform does not seem to
- * give maximum performance when all of CL_DEVICE_MAX_MEM_ALLOC_SIZE
- * is considered for further computation.
- */
- total_allocatable_memory /= 2;
- }
- }
+ OpenCLProgram program_state_buffer_size;
- virtual bool show_samples() const {
- return false;
- }
+ OpenCLDeviceSplitKernel(DeviceInfo& info, Stats &stats, bool background_);
- /* Split kernel utility functions. */
- size_t get_tex_size(const char *tex_name)
+ ~OpenCLDeviceSplitKernel()
{
- cl_mem ptr;
- size_t ret_size = 0;
- MemMap::iterator i = mem_map.find(tex_name);
- if(i != mem_map.end()) {
- ptr = CL_MEM_PTR(i->second);
- ciErr = clGetMemObjectInfo(ptr,
- CL_MEM_SIZE,
- sizeof(ret_size),
- &ret_size,
- NULL);
- assert(ciErr == CL_SUCCESS);
- }
- return ret_size;
+ task_pool.stop();
+
+ /* Release kernels */
+ program_data_init.release();
+
+ delete split_kernel;
}
- size_t get_shader_data_size(size_t max_closure)
+ virtual bool load_kernels(const DeviceRequestedFeatures& requested_features,
+ vector<OpenCLDeviceBase::OpenCLProgram*> &programs)
{
- /* ShaderData size with variable size ShaderClosure array */
- return sizeof(ShaderData) - (sizeof(ShaderClosure) * (MAX_CLOSURE - max_closure));
+ bool single_program = OpenCLInfo::use_single_program();
+ program_data_init = OpenCLDeviceBase::OpenCLProgram(this,
+ single_program ? "split" : "split_data_init",
+ single_program ? "kernel_split.cl" : "kernel_data_init.cl",
+ get_build_options(this, requested_features));
+
+ program_data_init.add_kernel(ustring("path_trace_data_init"));
+ programs.push_back(&program_data_init);
+
+ program_state_buffer_size = OpenCLDeviceBase::OpenCLProgram(this,
+ single_program ? "split" : "split_state_buffer_size",
+ single_program ? "kernel_split.cl" : "kernel_state_buffer_size.cl",
+ get_build_options(this, requested_features));
+ program_state_buffer_size.add_kernel(ustring("path_trace_state_buffer_size"));
+ programs.push_back(&program_state_buffer_size);
+
+ return split_kernel->load_kernels(requested_features);
}
- /* Returns size of KernelGlobals structure associated with OpenCL. */
- size_t get_KernelGlobals_size()
+ void thread_run(DeviceTask *task)
{
- /* Copy dummy KernelGlobals related to OpenCL from kernel_globals.h to
- * fetch its size.
- */
- typedef struct KernelGlobals {
- ccl_constant KernelData *data;
+ if(task->type == DeviceTask::FILM_CONVERT) {
+ film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
+ }
+ else if(task->type == DeviceTask::SHADER) {
+ shader(*task);
+ }
+ else if(task->type == DeviceTask::PATH_TRACE) {
+ RenderTile tile;
+
+ /* Copy dummy KernelGlobals related to OpenCL from kernel_globals.h to
+ * fetch its size.
+ */
+ typedef struct KernelGlobals {
+ ccl_constant KernelData *data;
#define KERNEL_TEX(type, ttype, name) \
- ccl_global type *name;
-#include "kernel_textures.h"
+ ccl_global type *name;
+#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
- void *sd_input;
- void *isect_shadow;
- } KernelGlobals;
+ SplitData split_data;
+ SplitParams split_param_data;
+ } KernelGlobals;
+
+ /* Allocate buffer for kernel globals */
+ device_memory kgbuffer;
+ kgbuffer.resize(sizeof(KernelGlobals));
+ mem_alloc("kernel_globals", kgbuffer, MEM_READ_WRITE);
+
+ /* Keep rendering tiles until done. */
+ while(task->acquire_tile(this, tile)) {
+ split_kernel->path_trace(task,
+ tile,
+ kgbuffer,
+ *const_mem_map["__data"]);
+
+ /* Complete kernel execution before release tile. */
+ /* This helps in multi-device render;
+ * The device that reaches the critical-section function
+ * release_tile waits (stalling other devices from entering
+ * release_tile) for all kernels to complete. If device1 (a
+ * slow-render device) reaches release_tile first then it would
+ * stall device2 (a fast-render device) from proceeding to render
+ * next tile.
+ */
+ clFinish(cqCommandQueue);
- return sizeof(KernelGlobals);
+ task->release_tile(tile);
+ }
+
+ mem_free(kgbuffer);
+ }
+ }
+
+protected:
+ /* ** Those guys are for workign around some compiler-specific bugs ** */
+
+ string build_options_for_base_program(
+ const DeviceRequestedFeatures& requested_features)
+ {
+ return requested_features.get_build_options();
}
- virtual void load_kernels(const DeviceRequestedFeatures& requested_features,
- vector<OpenCLProgram*> &programs)
+ friend class OpenCLSplitKernel;
+ friend class OpenCLSplitKernelFunction;
+};
+
+class OpenCLSplitKernelFunction : public SplitKernelFunction {
+public:
+ OpenCLDeviceSplitKernel* device;
+ OpenCLDeviceBase::OpenCLProgram program;
+
+ OpenCLSplitKernelFunction(OpenCLDeviceSplitKernel* device) : device(device) {}
+ ~OpenCLSplitKernelFunction() { program.release(); }
+
+ virtual bool enqueue(const KernelDimensions& dim, device_memory& kg, device_memory& data)
{
- string build_options = "-D__SPLIT_KERNEL__ ";
-#ifdef __WORK_STEALING__
- build_options += "-D__WORK_STEALING__ ";
-#endif
- build_options += requested_features.get_build_options();
-
- /* Set compute device build option. */
- cl_device_type device_type;
- ciErr = clGetDeviceInfo(cdDevice,
- CL_DEVICE_TYPE,
- sizeof(cl_device_type),
- &device_type,
- NULL);
- assert(ciErr == CL_SUCCESS);
- if(device_type == CL_DEVICE_TYPE_GPU) {
- build_options += " -D__COMPUTE_DEVICE_GPU__";
+ device->kernel_set_args(program(), 0, kg, data);
+
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ program(),
+ 2,
+ NULL,
+ dim.global_size,
+ dim.local_size,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ if(device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
+ return false;
}
-#define GLUE(a, b) a ## b
-#define LOAD_KERNEL(name) \
- do { \
- GLUE(program_, name) = OpenCLProgram(this, "split_" #name, "kernel_" #name ".cl", build_options); \
- GLUE(program_, name).add_kernel(ustring("path_trace_" #name)); \
- programs.push_back(&GLUE(program_, name)); \
- } while(false)
-
- LOAD_KERNEL(data_init);
- LOAD_KERNEL(scene_intersect);
- LOAD_KERNEL(lamp_emission);
- LOAD_KERNEL(queue_enqueue);
- LOAD_KERNEL(background_buffer_update);
- LOAD_KERNEL(shader_eval);
- LOAD_KERNEL(holdout_emission_blurring_pathtermination_ao);
- LOAD_KERNEL(direct_lighting);
- LOAD_KERNEL(shadow_blocked);
- LOAD_KERNEL(next_iteration_setup);
- LOAD_KERNEL(sum_all_radiance);
-
-#undef FIND_KERNEL
-#undef GLUE
-
- current_max_closure = requested_features.max_closure;
+ return true;
}
+};
- ~OpenCLDeviceSplitKernel()
+class OpenCLSplitKernel : public DeviceSplitKernel {
+ OpenCLDeviceSplitKernel *device;
+public:
+ explicit OpenCLSplitKernel(OpenCLDeviceSplitKernel *device) : DeviceSplitKernel(device), device(device) {
+ }
+
+ virtual SplitKernelFunction* get_split_kernel_function(string kernel_name,
+ const DeviceRequestedFeatures& requested_features)
{
- task_pool.stop();
+ OpenCLSplitKernelFunction* kernel = new OpenCLSplitKernelFunction(device);
- /* Release kernels */
- program_data_init.release();
- program_scene_intersect.release();
- program_lamp_emission.release();
- program_queue_enqueue.release();
- program_background_buffer_update.release();
- program_shader_eval.release();
- program_holdout_emission_blurring_pathtermination_ao.release();
- program_direct_lighting.release();
- program_shadow_blocked.release();
- program_next_iteration_setup.release();
- program_sum_all_radiance.release();
-
- /* Release global memory */
- release_mem_object_safe(rng_coop);
- release_mem_object_safe(throughput_coop);
- release_mem_object_safe(L_transparent_coop);
- release_mem_object_safe(PathRadiance_coop);
- release_mem_object_safe(Ray_coop);
- release_mem_object_safe(PathState_coop);
- release_mem_object_safe(Intersection_coop);
- release_mem_object_safe(kgbuffer);
- release_mem_object_safe(sd);
- release_mem_object_safe(sd_DL_shadow);
- release_mem_object_safe(ray_state);
- release_mem_object_safe(AOAlpha_coop);
- release_mem_object_safe(AOBSDF_coop);
- release_mem_object_safe(AOLightRay_coop);
- release_mem_object_safe(BSDFEval_coop);
- release_mem_object_safe(ISLamp_coop);
- release_mem_object_safe(LightRay_coop);
- release_mem_object_safe(Intersection_coop_shadow);
-#ifdef WITH_CYCLES_DEBUG
- release_mem_object_safe(debugdata_coop);
-#endif
- release_mem_object_safe(use_queues_flag);
- release_mem_object_safe(Queue_data);
- release_mem_object_safe(Queue_index);
- release_mem_object_safe(work_array);
-#ifdef __WORK_STEALING__
- release_mem_object_safe(work_pool_wgs);
-#endif
- release_mem_object_safe(per_sample_output_buffers);
-
- if(hostRayStateArray != NULL) {
- free(hostRayStateArray);
+ bool single_program = OpenCLInfo::use_single_program();
+ kernel->program =
+ OpenCLDeviceBase::OpenCLProgram(device,
+ single_program ? "split" : "split_" + kernel_name,
+ single_program ? "kernel_split.cl" : "kernel_" + kernel_name + ".cl",
+ get_build_options(device, requested_features));
+
+ kernel->program.add_kernel(ustring("path_trace_" + kernel_name));
+ kernel->program.load();
+
+ if(!kernel->program.is_loaded()) {
+ delete kernel;
+ return NULL;
}
+
+ return kernel;
}
- void path_trace(DeviceTask *task,
- SplitRenderTile& rtile,
- int2 max_render_feasible_tile_size)
+ virtual uint64_t state_buffer_size(device_memory& kg, device_memory& data, size_t num_threads)
{
- /* cast arguments to cl types */
- cl_mem d_data = CL_MEM_PTR(const_mem_map["__data"]->device_pointer);
- cl_mem d_buffer = CL_MEM_PTR(rtile.buffer);
- cl_mem d_rng_state = CL_MEM_PTR(rtile.rng_state);
- cl_int d_x = rtile.x;
- cl_int d_y = rtile.y;
- cl_int d_w = rtile.w;
- cl_int d_h = rtile.h;
- cl_int d_offset = rtile.offset;
- cl_int d_stride = rtile.stride;
-
- /* Make sure that set render feasible tile size is a multiple of local
- * work size dimensions.
- */
- assert(max_render_feasible_tile_size.x % SPLIT_KERNEL_LOCAL_SIZE_X == 0);
- assert(max_render_feasible_tile_size.y % SPLIT_KERNEL_LOCAL_SIZE_Y == 0);
+ device_vector<uint64_t> size_buffer;
+ size_buffer.resize(1);
+ device->mem_alloc(NULL, size_buffer, MEM_READ_WRITE);
+
+ uint threads = num_threads;
+ device->kernel_set_args(device->program_state_buffer_size(), 0, kg, data, threads, size_buffer);
+
+ size_t global_size = 64;
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ device->program_state_buffer_size(),
+ 1,
+ NULL,
+ &global_size,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ device->mem_copy_from(size_buffer, 0, 1, 1, sizeof(uint64_t));
+ device->mem_free(size_buffer);
+
+ if(device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
+ return 0;
+ }
+
+ return *size_buffer.get_data();
+ }
- size_t global_size[2];
- size_t local_size[2] = {SPLIT_KERNEL_LOCAL_SIZE_X,
- SPLIT_KERNEL_LOCAL_SIZE_Y};
+ virtual bool enqueue_split_kernel_data_init(const KernelDimensions& dim,
+ RenderTile& rtile,
+ int num_global_elements,
+ device_memory& kernel_globals,
+ device_memory& kernel_data,
+ device_memory& split_data,
+ device_memory& ray_state,
+ device_memory& queue_index,
+ device_memory& use_queues_flag,
+ device_memory& work_pool_wgs
+ )
+ {
+ cl_int dQueue_size = dim.global_size[0] * dim.global_size[1];
/* Set the range of samples to be processed for every ray in
* path-regeneration logic.
*/
cl_int start_sample = rtile.start_sample;
cl_int end_sample = rtile.start_sample + rtile.num_samples;
- cl_int num_samples = rtile.num_samples;
-
-#ifdef __WORK_STEALING__
- global_size[0] = (((d_w - 1) / local_size[0]) + 1) * local_size[0];
- global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1];
- unsigned int num_parallel_samples = 1;
-#else
- global_size[1] = (((d_h - 1) / local_size[1]) + 1) * local_size[1];
- unsigned int num_threads = max_render_feasible_tile_size.x *
- max_render_feasible_tile_size.y;
- unsigned int num_tile_columns_possible = num_threads / global_size[1];
- /* Estimate number of parallel samples that can be
- * processed in parallel.
- */
- unsigned int num_parallel_samples = min(num_tile_columns_possible / d_w,
- rtile.num_samples);
- /* Wavefront size in AMD is 64.
- * TODO(sergey): What about other platforms?
- */
- if(num_parallel_samples >= 64) {
- /* TODO(sergey): Could use generic round-up here. */
- num_parallel_samples = (num_parallel_samples / 64) * 64;
- }
- assert(num_parallel_samples != 0);
-
- global_size[0] = d_w * num_parallel_samples;
-#endif /* __WORK_STEALING__ */
-
- assert(global_size[0] * global_size[1] <=
- max_render_feasible_tile_size.x * max_render_feasible_tile_size.y);
-
- /* Allocate all required global memory once. */
- if(first_tile) {
- size_t num_global_elements = max_render_feasible_tile_size.x *
- max_render_feasible_tile_size.y;
- /* TODO(sergey): This will actually over-allocate if
- * particular kernel does not support multiclosure.
- */
- size_t shaderdata_size = get_shader_data_size(current_max_closure);
-
-#ifdef __WORK_STEALING__
- /* Calculate max groups */
- size_t max_global_size[2];
- size_t tile_x = max_render_feasible_tile_size.x;
- size_t tile_y = max_render_feasible_tile_size.y;
- max_global_size[0] = (((tile_x - 1) / local_size[0]) + 1) * local_size[0];
- max_global_size[1] = (((tile_y - 1) / local_size[1]) + 1) * local_size[1];
- max_work_groups = (max_global_size[0] * max_global_size[1]) /
- (local_size[0] * local_size[1]);
- /* Allocate work_pool_wgs memory. */
- work_pool_wgs = mem_alloc(max_work_groups * sizeof(unsigned int));
-#endif /* __WORK_STEALING__ */
-
- /* Allocate queue_index memory only once. */
- Queue_index = mem_alloc(NUM_QUEUES * sizeof(int));
- use_queues_flag = mem_alloc(sizeof(char));
- kgbuffer = mem_alloc(get_KernelGlobals_size());
-
- /* Create global buffers for ShaderData. */
- sd = mem_alloc(num_global_elements * shaderdata_size);
- sd_DL_shadow = mem_alloc(num_global_elements * 2 * shaderdata_size);
-
- /* Creation of global memory buffers which are shared among
- * the kernels.
- */
- rng_coop = mem_alloc(num_global_elements * sizeof(RNG));
- throughput_coop = mem_alloc(num_global_elements * sizeof(float3));
- L_transparent_coop = mem_alloc(num_global_elements * sizeof(float));
- PathRadiance_coop = mem_alloc(num_global_elements * sizeof(PathRadiance));
- Ray_coop = mem_alloc(num_global_elements * sizeof(Ray));
- PathState_coop = mem_alloc(num_global_elements * sizeof(PathState));
- Intersection_coop = mem_alloc(num_global_elements * sizeof(Intersection));
- AOAlpha_coop = mem_alloc(num_global_elements * sizeof(float3));
- AOBSDF_coop = mem_alloc(num_global_elements * sizeof(float3));
- AOLightRay_coop = mem_alloc(num_global_elements * sizeof(Ray));
- BSDFEval_coop = mem_alloc(num_global_elements * sizeof(BsdfEval));
- ISLamp_coop = mem_alloc(num_global_elements * sizeof(int));
- LightRay_coop = mem_alloc(num_global_elements * sizeof(Ray));
- Intersection_coop_shadow = mem_alloc(2 * num_global_elements * sizeof(Intersection));
-
-#ifdef WITH_CYCLES_DEBUG
- debugdata_coop = mem_alloc(num_global_elements * sizeof(DebugData));
-#endif
-
- ray_state = mem_alloc(num_global_elements * sizeof(char));
-
- hostRayStateArray = (char *)calloc(num_global_elements, sizeof(char));
- assert(hostRayStateArray != NULL && "Can't create hostRayStateArray memory");
-
- Queue_data = mem_alloc(num_global_elements * (NUM_QUEUES * sizeof(int)+sizeof(int)));
- work_array = mem_alloc(num_global_elements * sizeof(unsigned int));
- per_sample_output_buffers = mem_alloc(num_global_elements *
- per_thread_output_buffer_size);
- }
-
- cl_int dQueue_size = global_size[0] * global_size[1];
cl_uint start_arg_index =
- kernel_set_args(program_data_init(),
+ device->kernel_set_args(device->program_data_init(),
0,
- kgbuffer,
- sd_DL_shadow,
- d_data,
- per_sample_output_buffers,
- d_rng_state,
- rng_coop,
- throughput_coop,
- L_transparent_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop_shadow,
- ray_state);
+ kernel_globals,
+ kernel_data,
+ split_data,
+ num_global_elements,
+ ray_state,
+ rtile.rng_state);
/* TODO(sergey): Avoid map lookup here. */
#define KERNEL_TEX(type, ttype, name) \
- set_kernel_arg_mem(program_data_init(), &start_arg_index, #name);
-#include "kernel_textures.h"
+ device->set_kernel_arg_mem(device->program_data_init(), &start_arg_index, #name);
+#include "kernel/kernel_textures.h"
#undef KERNEL_TEX
start_arg_index +=
- kernel_set_args(program_data_init(),
+ device->kernel_set_args(device->program_data_init(),
start_arg_index,
start_sample,
- d_x,
- d_y,
- d_w,
- d_h,
- d_offset,
- d_stride,
- rtile.rng_state_offset_x,
- rtile.rng_state_offset_y,
- rtile.buffer_rng_state_stride,
- Queue_data,
- Queue_index,
+ end_sample,
+ rtile.x,
+ rtile.y,
+ rtile.w,
+ rtile.h,
+ rtile.offset,
+ rtile.stride,
+ queue_index,
dQueue_size,
use_queues_flag,
- work_array,
-#ifdef __WORK_STEALING__
work_pool_wgs,
- num_samples,
-#endif
-#ifdef WITH_CYCLES_DEBUG
- debugdata_coop,
-#endif
- num_parallel_samples);
-
- kernel_set_args(program_scene_intersect(),
- 0,
- kgbuffer,
- d_data,
- rng_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- d_w,
- d_h,
- Queue_data,
- Queue_index,
- dQueue_size,
- use_queues_flag,
-#ifdef WITH_CYCLES_DEBUG
- debugdata_coop,
-#endif
- num_parallel_samples);
-
- kernel_set_args(program_lamp_emission(),
- 0,
- kgbuffer,
- d_data,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- d_w,
- d_h,
- Queue_data,
- Queue_index,
- dQueue_size,
- use_queues_flag,
- num_parallel_samples);
-
- kernel_set_args(program_queue_enqueue(),
- 0,
- Queue_data,
- Queue_index,
- ray_state,
- dQueue_size);
-
- kernel_set_args(program_background_buffer_update(),
- 0,
- kgbuffer,
- d_data,
- per_sample_output_buffers,
- d_rng_state,
- rng_coop,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- L_transparent_coop,
- ray_state,
- d_w,
- d_h,
- d_x,
- d_y,
- d_stride,
- rtile.rng_state_offset_x,
- rtile.rng_state_offset_y,
- rtile.buffer_rng_state_stride,
- work_array,
- Queue_data,
- Queue_index,
- dQueue_size,
- end_sample,
- start_sample,
-#ifdef __WORK_STEALING__
- work_pool_wgs,
- num_samples,
-#endif
-#ifdef WITH_CYCLES_DEBUG
- debugdata_coop,
-#endif
- num_parallel_samples);
-
- kernel_set_args(program_shader_eval(),
- 0,
- kgbuffer,
- d_data,
- sd,
- rng_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- Queue_data,
- Queue_index,
- dQueue_size);
-
- kernel_set_args(program_holdout_emission_blurring_pathtermination_ao(),
- 0,
- kgbuffer,
- d_data,
- sd,
- per_sample_output_buffers,
- rng_coop,
- throughput_coop,
- L_transparent_coop,
- PathRadiance_coop,
- PathState_coop,
- Intersection_coop,
- AOAlpha_coop,
- AOBSDF_coop,
- AOLightRay_coop,
- d_w,
- d_h,
- d_x,
- d_y,
- d_stride,
- ray_state,
- work_array,
- Queue_data,
- Queue_index,
- dQueue_size,
-#ifdef __WORK_STEALING__
- start_sample,
-#endif
- num_parallel_samples);
-
- kernel_set_args(program_direct_lighting(),
- 0,
- kgbuffer,
- d_data,
- sd,
- rng_coop,
- PathState_coop,
- ISLamp_coop,
- LightRay_coop,
- BSDFEval_coop,
- ray_state,
- Queue_data,
- Queue_index,
- dQueue_size);
-
- kernel_set_args(program_shadow_blocked(),
- 0,
- kgbuffer,
- d_data,
- PathState_coop,
- LightRay_coop,
- AOLightRay_coop,
- ray_state,
- Queue_data,
- Queue_index,
- dQueue_size);
-
- kernel_set_args(program_next_iteration_setup(),
- 0,
- kgbuffer,
- d_data,
- sd,
- rng_coop,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- LightRay_coop,
- ISLamp_coop,
- BSDFEval_coop,
- AOLightRay_coop,
- AOBSDF_coop,
- AOAlpha_coop,
- ray_state,
- Queue_data,
- Queue_index,
- dQueue_size,
- use_queues_flag);
-
- kernel_set_args(program_sum_all_radiance(),
- 0,
- d_data,
- d_buffer,
- per_sample_output_buffers,
- num_parallel_samples,
- d_w,
- d_h,
- d_stride,
- rtile.buffer_offset_x,
- rtile.buffer_offset_y,
- rtile.buffer_rng_state_stride,
- start_sample);
-
- /* Macro for Enqueuing split kernels. */
-#define GLUE(a, b) a ## b
-#define ENQUEUE_SPLIT_KERNEL(kernelName, globalSize, localSize) \
- { \
- ciErr = clEnqueueNDRangeKernel(cqCommandQueue, \
- GLUE(program_, \
- kernelName)(), \
- 2, \
- NULL, \
- globalSize, \
- localSize, \
- 0, \
- NULL, \
- NULL); \
- opencl_assert_err(ciErr, "clEnqueueNDRangeKernel"); \
- if(ciErr != CL_SUCCESS) { \
- string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()", \
- clewErrorString(ciErr)); \
- opencl_error(message); \
- return; \
- } \
- } (void) 0
+ rtile.num_samples,
+ rtile.buffer);
/* Enqueue ckPathTraceKernel_data_init kernel. */
- ENQUEUE_SPLIT_KERNEL(data_init, global_size, local_size);
- bool activeRaysAvailable = true;
-
- /* Record number of time host intervention has been made */
- unsigned int numHostIntervention = 0;
- unsigned int numNextPathIterTimes = PathIteration_times;
- bool canceled = false;
- while(activeRaysAvailable) {
- /* Twice the global work size of other kernels for
- * ckPathTraceKernel_shadow_blocked_direct_lighting. */
- size_t global_size_shadow_blocked[2];
- global_size_shadow_blocked[0] = global_size[0] * 2;
- global_size_shadow_blocked[1] = global_size[1];
-
- /* Do path-iteration in host [Enqueue Path-iteration kernels. */
- for(int PathIter = 0; PathIter < PathIteration_times; PathIter++) {
- ENQUEUE_SPLIT_KERNEL(scene_intersect, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(lamp_emission, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(queue_enqueue, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(background_buffer_update, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(shader_eval, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(holdout_emission_blurring_pathtermination_ao, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(direct_lighting, global_size, local_size);
- ENQUEUE_SPLIT_KERNEL(shadow_blocked, global_size_shadow_blocked, local_size);
- ENQUEUE_SPLIT_KERNEL(next_iteration_setup, global_size, local_size);
-
- if(task->get_cancel()) {
- canceled = true;
- break;
- }
- }
-
- /* Read ray-state into Host memory to decide if we should exit
- * path-iteration in host.
- */
- ciErr = clEnqueueReadBuffer(cqCommandQueue,
- ray_state,
- CL_TRUE,
- 0,
- global_size[0] * global_size[1] * sizeof(char),
- hostRayStateArray,
- 0,
- NULL,
- NULL);
- assert(ciErr == CL_SUCCESS);
-
- activeRaysAvailable = false;
-
- for(int rayStateIter = 0;
- rayStateIter < global_size[0] * global_size[1];
- ++rayStateIter)
- {
- if(int8_t(hostRayStateArray[rayStateIter]) != RAY_INACTIVE) {
- /* Not all rays are RAY_INACTIVE. */
- activeRaysAvailable = true;
- break;
- }
- }
-
- if(activeRaysAvailable) {
- numHostIntervention++;
- PathIteration_times = PATH_ITER_INC_FACTOR;
- /* Host intervention done before all rays become RAY_INACTIVE;
- * Set do more initial iterations for the next tile.
- */
- numNextPathIterTimes += PATH_ITER_INC_FACTOR;
- }
-
- if(task->get_cancel()) {
- canceled = true;
- break;
- }
- }
-
- /* Execute SumALLRadiance kernel to accumulate radiance calculated in
- * per_sample_output_buffers into RenderTile's output buffer.
- */
- if(!canceled) {
- size_t sum_all_radiance_local_size[2] = {16, 16};
- size_t sum_all_radiance_global_size[2];
- sum_all_radiance_global_size[0] =
- (((d_w - 1) / sum_all_radiance_local_size[0]) + 1) *
- sum_all_radiance_local_size[0];
- sum_all_radiance_global_size[1] =
- (((d_h - 1) / sum_all_radiance_local_size[1]) + 1) *
- sum_all_radiance_local_size[1];
- ENQUEUE_SPLIT_KERNEL(sum_all_radiance,
- sum_all_radiance_global_size,
- sum_all_radiance_local_size);
- }
-
-#undef ENQUEUE_SPLIT_KERNEL
-#undef GLUE
-
- if(numHostIntervention == 0) {
- /* This means that we are executing kernel more than required
- * Must avoid this for the next sample/tile.
- */
- PathIteration_times = ((numNextPathIterTimes - PATH_ITER_INC_FACTOR) <= 0) ?
- PATH_ITER_INC_FACTOR : numNextPathIterTimes - PATH_ITER_INC_FACTOR;
- }
- else {
- /* Number of path-iterations done for this tile is set as
- * Initial path-iteration times for the next tile
- */
- PathIteration_times = numNextPathIterTimes;
- }
-
- first_tile = false;
- }
-
- /* Calculates the amount of memory that has to be always
- * allocated in order for the split kernel to function.
- * This memory is tile/scene-property invariant (meaning,
- * the value returned by this function does not depend
- * on the user set tile size or scene properties.
- */
- size_t get_invariable_mem_allocated()
- {
- size_t total_invariable_mem_allocated = 0;
- size_t KernelGlobals_size = 0;
-
- KernelGlobals_size = get_KernelGlobals_size();
-
- total_invariable_mem_allocated += KernelGlobals_size; /* KernelGlobals size */
- total_invariable_mem_allocated += NUM_QUEUES * sizeof(unsigned int); /* Queue index size */
- total_invariable_mem_allocated += sizeof(char); /* use_queues_flag size */
-
- return total_invariable_mem_allocated;
- }
-
- /* Calculate the memory that has-to-be/has-been allocated for
- * the split kernel to function.
- */
- size_t get_tile_specific_mem_allocated(const int2 tile_size)
- {
- size_t tile_specific_mem_allocated = 0;
-
- /* Get required tile info */
- unsigned int user_set_tile_w = tile_size.x;
- unsigned int user_set_tile_h = tile_size.y;
-
-#ifdef __WORK_STEALING__
- /* Calculate memory to be allocated for work_pools in
- * case of work_stealing.
- */
- size_t max_global_size[2];
- size_t max_num_work_pools = 0;
- max_global_size[0] =
- (((user_set_tile_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- max_global_size[1] =
- (((user_set_tile_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- max_num_work_pools =
- (max_global_size[0] * max_global_size[1]) /
- (SPLIT_KERNEL_LOCAL_SIZE_X * SPLIT_KERNEL_LOCAL_SIZE_Y);
- tile_specific_mem_allocated += max_num_work_pools * sizeof(unsigned int);
-#endif
-
- tile_specific_mem_allocated +=
- user_set_tile_w * user_set_tile_h * per_thread_output_buffer_size;
- tile_specific_mem_allocated +=
- user_set_tile_w * user_set_tile_h * sizeof(RNG);
-
- return tile_specific_mem_allocated;
- }
-
- /* Calculates the texture memories and KernelData (d_data) memory
- * that has been allocated.
- */
- size_t get_scene_specific_mem_allocated(cl_mem d_data)
- {
- size_t scene_specific_mem_allocated = 0;
- /* Calculate texture memories. */
-#define KERNEL_TEX(type, ttype, name) \
- scene_specific_mem_allocated += get_tex_size(#name);
-#include "kernel_textures.h"
-#undef KERNEL_TEX
- size_t d_data_size;
- ciErr = clGetMemObjectInfo(d_data,
- CL_MEM_SIZE,
- sizeof(d_data_size),
- &d_data_size,
- NULL);
- assert(ciErr == CL_SUCCESS && "Can't get d_data mem object info");
- scene_specific_mem_allocated += d_data_size;
- return scene_specific_mem_allocated;
- }
-
- /* Calculate the memory required for one thread in split kernel. */
- size_t get_per_thread_memory()
- {
- size_t shaderdata_size = 0;
- /* TODO(sergey): This will actually over-allocate if
- * particular kernel does not support multiclosure.
- */
- shaderdata_size = get_shader_data_size(current_max_closure);
- size_t retval = sizeof(RNG)
- + sizeof(float3) /* Throughput size */
- + sizeof(float) /* L transparent size */
- + sizeof(char) /* Ray state size */
- + sizeof(unsigned int) /* Work element size */
- + sizeof(int) /* ISLamp_size */
- + sizeof(PathRadiance) + sizeof(Ray) + sizeof(PathState)
- + sizeof(Intersection) /* Overall isect */
- + sizeof(Intersection) /* Instersection_coop_AO */
- + sizeof(Intersection) /* Intersection coop DL */
- + shaderdata_size /* Overall ShaderData */
- + (shaderdata_size * 2) /* ShaderData : DL and shadow */
- + sizeof(Ray) + sizeof(BsdfEval)
- + sizeof(float3) /* AOAlpha size */
- + sizeof(float3) /* AOBSDF size */
- + sizeof(Ray)
- + (sizeof(int) * NUM_QUEUES)
- + per_thread_output_buffer_size;
- return retval;
- }
-
- /* Considers the total memory available in the device and
- * and returns the maximum global work size possible.
- */
- size_t get_feasible_global_work_size(int2 tile_size, cl_mem d_data)
- {
- /* Calculate invariably allocated memory. */
- size_t invariable_mem_allocated = get_invariable_mem_allocated();
- /* Calculate tile specific allocated memory. */
- size_t tile_specific_mem_allocated =
- get_tile_specific_mem_allocated(tile_size);
- /* Calculate scene specific allocated memory. */
- size_t scene_specific_mem_allocated =
- get_scene_specific_mem_allocated(d_data);
- /* Calculate total memory available for the threads in global work size. */
- size_t available_memory = total_allocatable_memory
- - invariable_mem_allocated
- - tile_specific_mem_allocated
- - scene_specific_mem_allocated
- - DATA_ALLOCATION_MEM_FACTOR;
- size_t per_thread_memory_required = get_per_thread_memory();
- return (available_memory / per_thread_memory_required);
- }
-
- /* Checks if the device has enough memory to render the whole tile;
- * If not, we should split single tile into multiple tiles of small size
- * and process them all.
- */
- bool need_to_split_tile(unsigned int d_w,
- unsigned int d_h,
- int2 max_render_feasible_tile_size)
- {
- size_t global_size_estimate[2];
- /* TODO(sergey): Such round-ups are in quite few places, need to replace
- * them with an utility macro.
- */
- global_size_estimate[0] =
- (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- global_size_estimate[1] =
- (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- if((global_size_estimate[0] * global_size_estimate[1]) >
- (max_render_feasible_tile_size.x * max_render_feasible_tile_size.y))
- {
- return true;
- }
- else {
+ device->ciErr = clEnqueueNDRangeKernel(device->cqCommandQueue,
+ device->program_data_init(),
+ 2,
+ NULL,
+ dim.global_size,
+ dim.local_size,
+ 0,
+ NULL,
+ NULL);
+
+ device->opencl_assert_err(device->ciErr, "clEnqueueNDRangeKernel");
+
+ if(device->ciErr != CL_SUCCESS) {
+ string message = string_printf("OpenCL error: %s in clEnqueueNDRangeKernel()",
+ clewErrorString(device->ciErr));
+ device->opencl_error(message);
return false;
}
- }
- /* Considers the scene properties, global memory available in the device
- * and returns a rectanglular tile dimension (approx the maximum)
- * that should render on split kernel.
- */
- int2 get_max_render_feasible_tile_size(size_t feasible_global_work_size)
- {
- int2 max_render_feasible_tile_size;
- int square_root_val = (int)sqrt(feasible_global_work_size);
- max_render_feasible_tile_size.x = square_root_val;
- max_render_feasible_tile_size.y = square_root_val;
- /* Ciel round-off max_render_feasible_tile_size. */
- int2 ceil_render_feasible_tile_size;
- ceil_render_feasible_tile_size.x =
- (((max_render_feasible_tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- ceil_render_feasible_tile_size.y =
- (((max_render_feasible_tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- if(ceil_render_feasible_tile_size.x * ceil_render_feasible_tile_size.y <=
- feasible_global_work_size)
- {
- return ceil_render_feasible_tile_size;
- }
- /* Floor round-off max_render_feasible_tile_size. */
- int2 floor_render_feasible_tile_size;
- floor_render_feasible_tile_size.x =
- (max_render_feasible_tile_size.x / SPLIT_KERNEL_LOCAL_SIZE_X) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- floor_render_feasible_tile_size.y =
- (max_render_feasible_tile_size.y / SPLIT_KERNEL_LOCAL_SIZE_Y) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- return floor_render_feasible_tile_size;
+ return true;
}
- /* Try splitting the current tile into multiple smaller
- * almost-square-tiles.
- */
- int2 get_split_tile_size(RenderTile rtile,
- int2 max_render_feasible_tile_size)
+ virtual int2 split_kernel_local_size()
{
- int2 split_tile_size;
- int num_global_threads = max_render_feasible_tile_size.x *
- max_render_feasible_tile_size.y;
- int d_w = rtile.w;
- int d_h = rtile.h;
- /* Ceil round off d_w and d_h */
- d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- while(d_w * d_h > num_global_threads) {
- /* Halve the longer dimension. */
- if(d_w >= d_h) {
- d_w = d_w / 2;
- d_w = (((d_w - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- }
- else {
- d_h = d_h / 2;
- d_h = (((d_h - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- }
- }
- split_tile_size.x = d_w;
- split_tile_size.y = d_h;
- return split_tile_size;
+ return make_int2(64, 1);
}
- /* Splits existing tile into multiple tiles of tile size split_tile_size. */
- vector<SplitRenderTile> split_tiles(RenderTile rtile, int2 split_tile_size)
+ virtual int2 split_kernel_global_size(device_memory& kg, device_memory& data, DeviceTask */*task*/)
{
- vector<SplitRenderTile> to_path_trace_rtile;
- int d_w = rtile.w;
- int d_h = rtile.h;
- int num_tiles_x = (((d_w - 1) / split_tile_size.x) + 1);
- int num_tiles_y = (((d_h - 1) / split_tile_size.y) + 1);
- /* Buffer and rng_state offset calc. */
- size_t offset_index = rtile.offset + (rtile.x + rtile.y * rtile.stride);
- size_t offset_x = offset_index % rtile.stride;
- size_t offset_y = offset_index / rtile.stride;
- /* Resize to_path_trace_rtile. */
- to_path_trace_rtile.resize(num_tiles_x * num_tiles_y);
- for(int tile_iter_y = 0; tile_iter_y < num_tiles_y; tile_iter_y++) {
- for(int tile_iter_x = 0; tile_iter_x < num_tiles_x; tile_iter_x++) {
- int rtile_index = tile_iter_y * num_tiles_x + tile_iter_x;
- to_path_trace_rtile[rtile_index].rng_state_offset_x = offset_x + tile_iter_x * split_tile_size.x;
- to_path_trace_rtile[rtile_index].rng_state_offset_y = offset_y + tile_iter_y * split_tile_size.y;
- to_path_trace_rtile[rtile_index].buffer_offset_x = offset_x + tile_iter_x * split_tile_size.x;
- to_path_trace_rtile[rtile_index].buffer_offset_y = offset_y + tile_iter_y * split_tile_size.y;
- to_path_trace_rtile[rtile_index].start_sample = rtile.start_sample;
- to_path_trace_rtile[rtile_index].num_samples = rtile.num_samples;
- to_path_trace_rtile[rtile_index].sample = rtile.sample;
- to_path_trace_rtile[rtile_index].resolution = rtile.resolution;
- to_path_trace_rtile[rtile_index].offset = rtile.offset;
- to_path_trace_rtile[rtile_index].buffers = rtile.buffers;
- to_path_trace_rtile[rtile_index].buffer = rtile.buffer;
- to_path_trace_rtile[rtile_index].rng_state = rtile.rng_state;
- to_path_trace_rtile[rtile_index].x = rtile.x + (tile_iter_x * split_tile_size.x);
- to_path_trace_rtile[rtile_index].y = rtile.y + (tile_iter_y * split_tile_size.y);
- to_path_trace_rtile[rtile_index].buffer_rng_state_stride = rtile.stride;
- /* Fill width and height of the new render tile. */
- to_path_trace_rtile[rtile_index].w = (tile_iter_x == (num_tiles_x - 1)) ?
- (d_w - (tile_iter_x * split_tile_size.x)) /* Border tile */
- : split_tile_size.x;
- to_path_trace_rtile[rtile_index].h = (tile_iter_y == (num_tiles_y - 1)) ?
- (d_h - (tile_iter_y * split_tile_size.y)) /* Border tile */
- : split_tile_size.y;
- to_path_trace_rtile[rtile_index].stride = to_path_trace_rtile[rtile_index].w;
- }
+ cl_device_type type = OpenCLInfo::get_device_type(device->cdDevice);
+ /* Use small global size on CPU devices as it seems to be much faster. */
+ if(type == CL_DEVICE_TYPE_CPU) {
+ VLOG(1) << "Global size: (64, 64).";
+ return make_int2(64, 64);
}
- return to_path_trace_rtile;
- }
- void thread_run(DeviceTask *task)
- {
- if(task->type == DeviceTask::FILM_CONVERT) {
- film_convert(*task, task->buffer, task->rgba_byte, task->rgba_half);
- }
- else if(task->type == DeviceTask::SHADER) {
- shader(*task);
- }
- else if(task->type == DeviceTask::PATH_TRACE) {
- RenderTile tile;
- bool initialize_data_and_check_render_feasibility = false;
- bool need_to_split_tiles_further = false;
- int2 max_render_feasible_tile_size;
- size_t feasible_global_work_size;
- const int2 tile_size = task->requested_tile_size;
- /* Keep rendering tiles until done. */
- while(task->acquire_tile(this, tile)) {
- if(!initialize_data_and_check_render_feasibility) {
- /* Initialize data. */
- /* Calculate per_thread_output_buffer_size. */
- size_t output_buffer_size = 0;
- ciErr = clGetMemObjectInfo((cl_mem)tile.buffer,
- CL_MEM_SIZE,
- sizeof(output_buffer_size),
- &output_buffer_size,
- NULL);
- assert(ciErr == CL_SUCCESS && "Can't get tile.buffer mem object info");
- /* This value is different when running on AMD and NV. */
- if(background) {
- /* In offline render the number of buffer elements
- * associated with tile.buffer is the current tile size.
- */
- per_thread_output_buffer_size =
- output_buffer_size / (tile.w * tile.h);
- }
- else {
- /* interactive rendering, unlike offline render, the number of buffer elements
- * associated with tile.buffer is the entire viewport size.
- */
- per_thread_output_buffer_size =
- output_buffer_size / (tile.buffers->params.width *
- tile.buffers->params.height);
- }
- /* Check render feasibility. */
- feasible_global_work_size = get_feasible_global_work_size(
- tile_size,
- CL_MEM_PTR(const_mem_map["__data"]->device_pointer));
- max_render_feasible_tile_size =
- get_max_render_feasible_tile_size(
- feasible_global_work_size);
- need_to_split_tiles_further =
- need_to_split_tile(tile_size.x,
- tile_size.y,
- max_render_feasible_tile_size);
- initialize_data_and_check_render_feasibility = true;
- }
- if(need_to_split_tiles_further) {
- int2 split_tile_size =
- get_split_tile_size(tile,
- max_render_feasible_tile_size);
- vector<SplitRenderTile> to_path_trace_render_tiles =
- split_tiles(tile, split_tile_size);
- /* Print message to console */
- if(background && (to_path_trace_render_tiles.size() > 1)) {
- fprintf(stderr, "Message : Tiles need to be split "
- "further inside path trace (due to insufficient "
- "device-global-memory for split kernel to "
- "function) \n"
- "The current tile of dimensions %dx%d is split "
- "into tiles of dimension %dx%d for render \n",
- tile.w, tile.h,
- split_tile_size.x,
- split_tile_size.y);
- }
- /* Process all split tiles. */
- for(int tile_iter = 0;
- tile_iter < to_path_trace_render_tiles.size();
- ++tile_iter)
- {
- path_trace(task,
- to_path_trace_render_tiles[tile_iter],
- max_render_feasible_tile_size);
- }
- }
- else {
- /* No splitting required; process the entire tile at once. */
- /* Render feasible tile size is user-set-tile-size itself. */
- max_render_feasible_tile_size.x =
- (((tile_size.x - 1) / SPLIT_KERNEL_LOCAL_SIZE_X) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_X;
- max_render_feasible_tile_size.y =
- (((tile_size.y - 1) / SPLIT_KERNEL_LOCAL_SIZE_Y) + 1) *
- SPLIT_KERNEL_LOCAL_SIZE_Y;
- /* buffer_rng_state_stride is stride itself. */
- SplitRenderTile split_tile(tile);
- split_tile.buffer_rng_state_stride = tile.stride;
- path_trace(task, split_tile, max_render_feasible_tile_size);
- }
- tile.sample = tile.start_sample + tile.num_samples;
+ cl_ulong max_buffer_size;
+ clGetDeviceInfo(device->cdDevice, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &max_buffer_size, NULL);
+ VLOG(1) << "Maximum device allocation size: "
+ << string_human_readable_number(max_buffer_size) << " bytes. ("
+ << string_human_readable_size(max_buffer_size) << ").";
- /* Complete kernel execution before release tile. */
- /* This helps in multi-device render;
- * The device that reaches the critical-section function
- * release_tile waits (stalling other devices from entering
- * release_tile) for all kernels to complete. If device1 (a
- * slow-render device) reaches release_tile first then it would
- * stall device2 (a fast-render device) from proceeding to render
- * next tile.
- */
- clFinish(cqCommandQueue);
-
- task->release_tile(tile);
- }
- }
- }
-
-protected:
- cl_mem mem_alloc(size_t bufsize, cl_mem_flags mem_flag = CL_MEM_READ_WRITE)
- {
- cl_mem ptr;
- assert(bufsize != 0);
- ptr = clCreateBuffer(cxContext, mem_flag, bufsize, NULL, &ciErr);
- opencl_assert_err(ciErr, "clCreateBuffer");
- return ptr;
+ size_t num_elements = max_elements_for_max_buffer_size(kg, data, max_buffer_size / 2);
+ int2 global_size = make_int2(round_down((int)sqrt(num_elements), 64), (int)sqrt(num_elements));
+ VLOG(1) << "Global size: " << global_size << ".";
+ return global_size;
}
+};
- /* ** Those guys are for workign around some compiler-specific bugs ** */
+OpenCLDeviceSplitKernel::OpenCLDeviceSplitKernel(DeviceInfo& info, Stats &stats, bool background_)
+: OpenCLDeviceBase(info, stats, background_)
+{
+ split_kernel = new OpenCLSplitKernel(this);
- string build_options_for_base_program(
- const DeviceRequestedFeatures& requested_features)
- {
- return requested_features.get_build_options();
- }
-};
+ background = background_;
+}
Device *opencl_create_split_device(DeviceInfo& info, Stats& stats, bool background)
{
diff --git a/intern/cycles/device/opencl/opencl_util.cpp b/intern/cycles/device/opencl/opencl_util.cpp
index 82e1640e508..8128fcee09b 100644
--- a/intern/cycles/device/opencl/opencl_util.cpp
+++ b/intern/cycles/device/opencl/opencl_util.cpp
@@ -16,11 +16,12 @@
#ifdef WITH_OPENCL
-#include "opencl.h"
+#include "device/opencl/opencl.h"
-#include "util_logging.h"
-#include "util_path.h"
-#include "util_time.h"
+#include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_time.h"
using std::cerr;
using std::endl;
@@ -234,7 +235,7 @@ string OpenCLCache::get_kernel_md5()
thread_scoped_lock lock(self.kernel_md5_lock);
if(self.kernel_md5.empty()) {
- self.kernel_md5 = path_files_md5_hash(path_get("kernel"));
+ self.kernel_md5 = path_files_md5_hash(path_get("source"));
}
return self.kernel_md5;
}
@@ -309,6 +310,8 @@ bool OpenCLDeviceBase::OpenCLProgram::build_kernel(const string *debug_src)
string build_options;
build_options = device->kernel_build_options(debug_src) + kernel_build_options;
+ VLOG(1) << "Build options passed to clBuildProgram: '"
+ << build_options << "'.";
cl_int ciErr = clBuildProgram(program, 0, NULL, build_options.c_str(), NULL, NULL);
/* show warnings even if build is successful */
@@ -336,12 +339,13 @@ bool OpenCLDeviceBase::OpenCLProgram::build_kernel(const string *debug_src)
bool OpenCLDeviceBase::OpenCLProgram::compile_kernel(const string *debug_src)
{
- string source = "#include \"kernels/opencl/" + kernel_file + "\" // " + OpenCLCache::get_kernel_md5() + "\n";
+ string source = "#include \"kernel/kernels/opencl/" + kernel_file + "\"\n";
/* We compile kernels consisting of many files. unfortunately OpenCL
* kernel caches do not seem to recognize changes in included files.
* so we force recompile on changes by adding the md5 hash of all files.
*/
- source = path_source_replace_includes(source, path_get("kernel"));
+ source = path_source_replace_includes(source, path_get("source"));
+ source += "\n// " + util_md5_string(source) + "\n";
if(debug_src) {
path_write_text(*debug_src, source);
@@ -352,10 +356,10 @@ bool OpenCLDeviceBase::OpenCLProgram::compile_kernel(const string *debug_src)
cl_int ciErr;
program = clCreateProgramWithSource(device->cxContext,
- 1,
- &source_str,
- &source_len,
- &ciErr);
+ 1,
+ &source_str,
+ &source_len,
+ &ciErr);
if(ciErr != CL_SUCCESS) {
add_error(string("OpenCL program creation failed: ") + clewErrorString(ciErr));
@@ -438,7 +442,11 @@ void OpenCLDeviceBase::OpenCLProgram::load()
if(!program) {
add_log(string("OpenCL program ") + program_name + " not found in cache.", true);
- string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" + OpenCLCache::get_kernel_md5();
+ /* need to create source to get md5 */
+ string source = "#include \"kernel/kernels/opencl/" + kernel_file + "\"\n";
+ source = path_source_replace_includes(source, path_get("source"));
+
+ string basename = "cycles_kernel_" + program_name + "_" + device_md5 + "_" + util_md5_string(source);
basename = path_cache_get(path_join("kernels", basename));
string clbin = basename + ".clbin";
@@ -544,6 +552,11 @@ bool OpenCLInfo::use_debug()
return DebugFlags().opencl.debug;
}
+bool OpenCLInfo::use_single_program()
+{
+ return DebugFlags().opencl.single_program;
+}
+
bool OpenCLInfo::kernel_use_advanced_shading(const string& platform)
{
/* keep this in sync with kernel_types.h! */
@@ -587,11 +600,20 @@ bool OpenCLInfo::device_supported(const string& platform_name,
const cl_device_id device_id)
{
cl_device_type device_type;
- clGetDeviceInfo(device_id,
- CL_DEVICE_TYPE,
- sizeof(cl_device_type),
- &device_type,
- NULL);
+ if(!get_device_type(device_id, &device_type)) {
+ return false;
+ }
+ string device_name;
+ if(!get_device_name(device_id, &device_name)) {
+ return false;
+ }
+ /* It is possible tyo have Iris GPU on AMD/Apple OpenCL framework
+ * (aka, it will not be on Intel framework). This isn't supported
+ * and needs an explicit blacklist.
+ */
+ if(strstr(device_name.c_str(), "Iris")) {
+ return false;
+ }
if(platform_name == "AMD Accelerated Parallel Processing" &&
device_type == CL_DEVICE_TYPE_GPU)
{
@@ -705,39 +727,30 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
return;
}
+ cl_int error;
vector<cl_device_id> device_ids;
- cl_uint num_devices = 0;
vector<cl_platform_id> platform_ids;
- cl_uint num_platforms = 0;
- /* Get devices. */
- if(clGetPlatformIDs(0, NULL, &num_platforms) != CL_SUCCESS ||
- num_platforms == 0)
- {
- FIRST_VLOG(2) << "No OpenCL platforms were found.";
+ /* Get platforms. */
+ if(!get_platforms(&platform_ids, &error)) {
+ FIRST_VLOG(2) << "Error fetching platforms:"
+ << string(clewErrorString(error));
first_time = false;
return;
}
- platform_ids.resize(num_platforms);
- if(clGetPlatformIDs(num_platforms, &platform_ids[0], NULL) != CL_SUCCESS) {
- FIRST_VLOG(2) << "Failed to fetch platform IDs from the driver..";
+ if(platform_ids.size() == 0) {
+ FIRST_VLOG(2) << "No OpenCL platforms were found.";
first_time = false;
return;
}
/* Devices are numbered consecutively across platforms. */
- for(int platform = 0; platform < num_platforms; platform++) {
+ for(int platform = 0; platform < platform_ids.size(); platform++) {
cl_platform_id platform_id = platform_ids[platform];
- char pname[256];
- if(clGetPlatformInfo(platform_id,
- CL_PLATFORM_NAME,
- sizeof(pname),
- &pname,
- NULL) != CL_SUCCESS)
- {
+ string platform_name;
+ if(!get_platform_name(platform_id, &platform_name)) {
FIRST_VLOG(2) << "Failed to get platform name, ignoring.";
continue;
}
- string platform_name = pname;
FIRST_VLOG(2) << "Enumerating devices for platform "
<< platform_name << ".";
if(!platform_version_check(platform_id)) {
@@ -745,39 +758,28 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
<< " due to too old compiler version.";
continue;
}
- num_devices = 0;
- cl_int ciErr;
- if((ciErr = clGetDeviceIDs(platform_id,
- device_type,
- 0,
- NULL,
- &num_devices)) != CL_SUCCESS || num_devices == 0)
+ if(!get_platform_devices(platform_id,
+ device_type,
+ &device_ids,
+ &error))
{
FIRST_VLOG(2) << "Ignoring platform " << platform_name
- << ", failed to fetch number of devices: " << string(clewErrorString(ciErr));
+ << ", failed to fetch of devices: "
+ << string(clewErrorString(error));
continue;
}
- device_ids.resize(num_devices);
- if(clGetDeviceIDs(platform_id,
- device_type,
- num_devices,
- &device_ids[0],
- NULL) != CL_SUCCESS)
- {
+ if(device_ids.size() == 0) {
FIRST_VLOG(2) << "Ignoring platform " << platform_name
- << ", failed to fetch devices list.";
+ << ", it has no devices.";
continue;
}
- for(int num = 0; num < num_devices; num++) {
- cl_device_id device_id = device_ids[num];
- char device_name[1024] = "\0";
- if(clGetDeviceInfo(device_id,
- CL_DEVICE_NAME,
- sizeof(device_name),
- &device_name,
- NULL) != CL_SUCCESS)
- {
- FIRST_VLOG(2) << "Failed to fetch device name, ignoring.";
+ for(int num = 0; num < device_ids.size(); num++) {
+ const cl_device_id device_id = device_ids[num];
+ string device_name;
+ if(!get_device_name(device_id, &device_name, &error)) {
+ FIRST_VLOG(2) << "Failed to fetch device name: "
+ << string(clewErrorString(error))
+ << ", ignoring.";
continue;
}
if(!device_version_check(device_id)) {
@@ -789,24 +791,28 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
device_supported(platform_name, device_id))
{
cl_device_type device_type;
- if(clGetDeviceInfo(device_id,
- CL_DEVICE_TYPE,
- sizeof(cl_device_type),
- &device_type,
- NULL) != CL_SUCCESS)
- {
+ if(!get_device_type(device_id, &device_type, &error)) {
FIRST_VLOG(2) << "Ignoring device " << device_name
- << ", failed to fetch device type.";
+ << ", failed to fetch device type:"
+ << string(clewErrorString(error));
continue;
}
- FIRST_VLOG(2) << "Adding new device " << device_name << ".";
+ string readable_device_name =
+ get_readable_device_name(device_id);
+ if(readable_device_name != device_name) {
+ FIRST_VLOG(2) << "Using more readable device name: "
+ << readable_device_name;
+ }
+ FIRST_VLOG(2) << "Adding new device "
+ << readable_device_name << ".";
string hardware_id = get_hardware_id(platform_name, device_id);
- usable_devices->push_back(OpenCLPlatformDevice(platform_id,
- platform_name,
- device_id,
- device_type,
- device_name,
- hardware_id));
+ usable_devices->push_back(OpenCLPlatformDevice(
+ platform_id,
+ platform_name,
+ device_id,
+ device_type,
+ readable_device_name,
+ hardware_id));
}
else {
FIRST_VLOG(2) << "Ignoring device " << device_name
@@ -817,6 +823,252 @@ void OpenCLInfo::get_usable_devices(vector<OpenCLPlatformDevice> *usable_devices
first_time = false;
}
+bool OpenCLInfo::get_platforms(vector<cl_platform_id> *platform_ids,
+ cl_int *error)
+{
+ /* Reset from possible previous state. */
+ platform_ids->resize(0);
+ cl_uint num_platforms;
+ if(!get_num_platforms(&num_platforms, error)) {
+ return false;
+ }
+ /* Get actual platforms. */
+ cl_int err;
+ platform_ids->resize(num_platforms);
+ if((err = clGetPlatformIDs(num_platforms,
+ &platform_ids->at(0),
+ NULL)) != CL_SUCCESS) {
+ if(error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
+}
+
+vector<cl_platform_id> OpenCLInfo::get_platforms()
+{
+ vector<cl_platform_id> platform_ids;
+ get_platforms(&platform_ids);
+ return platform_ids;
+}
+
+bool OpenCLInfo::get_num_platforms(cl_uint *num_platforms, cl_int *error)
+{
+ cl_int err;
+ if((err = clGetPlatformIDs(0, NULL, num_platforms)) != CL_SUCCESS) {
+ if(error != NULL) {
+ *error = err;
+ }
+ *num_platforms = 0;
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
+}
+
+cl_uint OpenCLInfo::get_num_platforms()
+{
+ cl_uint num_platforms;
+ if(!get_num_platforms(&num_platforms)) {
+ return 0;
+ }
+ return num_platforms;
+}
+
+bool OpenCLInfo::get_platform_name(cl_platform_id platform_id,
+ string *platform_name)
+{
+ char buffer[256];
+ if(clGetPlatformInfo(platform_id,
+ CL_PLATFORM_NAME,
+ sizeof(buffer),
+ &buffer,
+ NULL) != CL_SUCCESS)
+ {
+ *platform_name = "";
+ return false;
+ }
+ *platform_name = buffer;
+ return true;
+}
+
+string OpenCLInfo::get_platform_name(cl_platform_id platform_id)
+{
+ string platform_name;
+ if (!get_platform_name(platform_id, &platform_name)) {
+ return "";
+ }
+ return platform_name;
+}
+
+bool OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ cl_uint *num_devices,
+ cl_int *error)
+{
+ cl_int err;
+ if((err = clGetDeviceIDs(platform_id,
+ device_type,
+ 0,
+ NULL,
+ num_devices)) != CL_SUCCESS)
+ {
+ if(error != NULL) {
+ *error = err;
+ }
+ *num_devices = 0;
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
+}
+
+cl_uint OpenCLInfo::get_num_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type)
+{
+ cl_uint num_devices;
+ if(!get_num_platform_devices(platform_id,
+ device_type,
+ &num_devices))
+ {
+ return 0;
+ }
+ return num_devices;
+}
+
+bool OpenCLInfo::get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type,
+ vector<cl_device_id> *device_ids,
+ cl_int* error)
+{
+ /* Reset from possible previous state. */
+ device_ids->resize(0);
+ /* Get number of devices to pre-allocate memory. */
+ cl_uint num_devices;
+ if(!get_num_platform_devices(platform_id,
+ device_type,
+ &num_devices,
+ error))
+ {
+ return false;
+ }
+ /* Get actual device list. */
+ device_ids->resize(num_devices);
+ cl_int err;
+ if((err = clGetDeviceIDs(platform_id,
+ device_type,
+ num_devices,
+ &device_ids->at(0),
+ NULL)) != CL_SUCCESS)
+ {
+ if(error != NULL) {
+ *error = err;
+ }
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
+}
+
+vector<cl_device_id> OpenCLInfo::get_platform_devices(cl_platform_id platform_id,
+ cl_device_type device_type)
+{
+ vector<cl_device_id> devices;
+ get_platform_devices(platform_id, device_type, &devices);
+ return devices;
+}
+
+bool OpenCLInfo::get_device_name(cl_device_id device_id,
+ string *device_name,
+ cl_int* error)
+{
+ char buffer[1024];
+ cl_int err;
+ if((err = clGetDeviceInfo(device_id,
+ CL_DEVICE_NAME,
+ sizeof(buffer),
+ &buffer,
+ NULL)) != CL_SUCCESS)
+ {
+ if(error != NULL) {
+ *error = err;
+ }
+ *device_name = "";
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ *device_name = buffer;
+ return true;
+}
+
+string OpenCLInfo::get_device_name(cl_device_id device_id)
+{
+ string device_name;
+ if(!get_device_name(device_id, &device_name)) {
+ return "";
+ }
+ return device_name;
+}
+
+bool OpenCLInfo::get_device_type(cl_device_id device_id,
+ cl_device_type *device_type,
+ cl_int* error)
+{
+ cl_int err;
+ if((err = clGetDeviceInfo(device_id,
+ CL_DEVICE_TYPE,
+ sizeof(cl_device_type),
+ device_type,
+ NULL)) != CL_SUCCESS)
+ {
+ if(error != NULL) {
+ *error = err;
+ }
+ *device_type = 0;
+ return false;
+ }
+ if(error != NULL) {
+ *error = CL_SUCCESS;
+ }
+ return true;
+}
+
+cl_device_type OpenCLInfo::get_device_type(cl_device_id device_id)
+{
+ cl_device_type device_type;
+ if(!get_device_type(device_id, &device_type)) {
+ return 0;
+ }
+ return device_type;
+}
+
+string OpenCLInfo::get_readable_device_name(cl_device_id device_id)
+{
+ char board_name[1024];
+ if(clGetDeviceInfo(device_id,
+ CL_DEVICE_BOARD_NAME_AMD,
+ sizeof(board_name),
+ &board_name,
+ NULL) == CL_SUCCESS)
+ {
+ return board_name;
+ }
+ /* Fallback to standard device name API. */
+ return get_device_name(device_id);
+}
+
CCL_NAMESPACE_END
#endif
diff --git a/intern/cycles/graph/CMakeLists.txt b/intern/cycles/graph/CMakeLists.txt
index 4ea18728f1c..e70a18137bd 100644
--- a/intern/cycles/graph/CMakeLists.txt
+++ b/intern/cycles/graph/CMakeLists.txt
@@ -1,7 +1,6 @@
set(INC
- .
- ../util
+ ..
)
set(SRC
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index 3c228a716d5..10d91a1e4ef 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "node.h"
-#include "node_type.h"
+#include "graph/node.h"
+#include "graph/node_type.h"
-#include "util_foreach.h"
-#include "util_param.h"
-#include "util_transform.h"
+#include "util/util_foreach.h"
+#include "util/util_param.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 64410f4539b..53425f5faf1 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -16,11 +16,11 @@
#pragma once
-#include "node_type.h"
+#include "graph/node_type.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_vector.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node_enum.h b/intern/cycles/graph/node_enum.h
index 2bae531c036..4e40c294f4f 100644
--- a/intern/cycles/graph/node_enum.h
+++ b/intern/cycles/graph/node_enum.h
@@ -16,8 +16,8 @@
#pragma once
-#include "util_map.h"
-#include "util_param.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node_type.cpp b/intern/cycles/graph/node_type.cpp
index 5b98de778ad..a3a8fa5f382 100644
--- a/intern/cycles/graph/node_type.cpp
+++ b/intern/cycles/graph/node_type.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "node_type.h"
-#include "util_foreach.h"
-#include "util_transform.h"
+#include "graph/node_type.h"
+#include "util/util_foreach.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node_type.h b/intern/cycles/graph/node_type.h
index 1fb135f6d22..7d46e31ce24 100644
--- a/intern/cycles/graph/node_type.h
+++ b/intern/cycles/graph/node_type.h
@@ -16,12 +16,12 @@
#pragma once
-#include "node_enum.h"
+#include "graph/node_enum.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_string.h"
-#include "util_vector.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_string.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node_xml.cpp b/intern/cycles/graph/node_xml.cpp
index 590e09645ed..aad2740ffc0 100644
--- a/intern/cycles/graph/node_xml.cpp
+++ b/intern/cycles/graph/node_xml.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "node_xml.h"
+#include "graph/node_xml.h"
-#include "util_foreach.h"
-#include "util_string.h"
-#include "util_transform.h"
+#include "util/util_foreach.h"
+#include "util/util_string.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/graph/node_xml.h b/intern/cycles/graph/node_xml.h
index 7494c5e6e55..63e80bf79f2 100644
--- a/intern/cycles/graph/node_xml.h
+++ b/intern/cycles/graph/node_xml.h
@@ -16,11 +16,11 @@
#pragma once
-#include "node.h"
+#include "graph/node.h"
-#include "util_map.h"
-#include "util_string.h"
-#include "util_xml.h"
+#include "util/util_map.h"
+#include "util/util_string.h"
+#include "util/util_xml.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 29e0f44841e..dbc2ba2503a 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -1,10 +1,7 @@
remove_extra_strict_flags()
set(INC
- .
- ../util
- osl
- svm
+ ..
)
set(INC_SYS
@@ -13,19 +10,28 @@ set(INC_SYS
set(SRC
kernels/cpu/kernel.cpp
+ kernels/cpu/kernel_split.cpp
kernels/opencl/kernel.cl
+ kernels/opencl/kernel_state_buffer_size.cl
+ kernels/opencl/kernel_split.cl
kernels/opencl/kernel_data_init.cl
+ kernels/opencl/kernel_path_init.cl
kernels/opencl/kernel_queue_enqueue.cl
kernels/opencl/kernel_scene_intersect.cl
kernels/opencl/kernel_lamp_emission.cl
- kernels/opencl/kernel_background_buffer_update.cl
+ kernels/opencl/kernel_do_volume.cl
+ kernels/opencl/kernel_indirect_background.cl
kernels/opencl/kernel_shader_eval.cl
kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
+ kernels/opencl/kernel_subsurface_scatter.cl
kernels/opencl/kernel_direct_lighting.cl
- kernels/opencl/kernel_shadow_blocked.cl
+ kernels/opencl/kernel_shadow_blocked_ao.cl
+ kernels/opencl/kernel_shadow_blocked_dl.cl
kernels/opencl/kernel_next_iteration_setup.cl
- kernels/opencl/kernel_sum_all_radiance.cl
+ kernels/opencl/kernel_indirect_subsurface.cl
+ kernels/opencl/kernel_buffer_update.cl
kernels/cuda/kernel.cu
+ kernels/cuda/kernel_split.cu
)
set(SRC_BVH_HEADERS
@@ -68,6 +74,7 @@ set(SRC_HEADERS
kernel_path_common.h
kernel_path_state.h
kernel_path_surface.h
+ kernel_path_subsurface.h
kernel_path_volume.h
kernel_projection.h
kernel_queues.h
@@ -88,6 +95,10 @@ set(SRC_KERNELS_CPU_HEADERS
kernels/cpu/kernel_cpu_image.h
)
+set(SRC_KERNELS_CUDA_HEADERS
+ kernels/cuda/kernel_config.h
+)
+
set(SRC_CLOSURE_HEADERS
closure/alloc.h
closure/bsdf.h
@@ -182,6 +193,7 @@ set(SRC_UTIL_HEADERS
../util/util_hash.h
../util/util_math.h
../util/util_math_fast.h
+ ../util/util_math_intersect.h
../util/util_static_assert.h
../util/util_transform.h
../util/util_texture.h
@@ -189,17 +201,25 @@ set(SRC_UTIL_HEADERS
)
set(SRC_SPLIT_HEADERS
- split/kernel_background_buffer_update.h
+ split/kernel_buffer_update.h
split/kernel_data_init.h
split/kernel_direct_lighting.h
+ split/kernel_do_volume.h
split/kernel_holdout_emission_blurring_pathtermination_ao.h
+ split/kernel_indirect_background.h
+ split/kernel_indirect_subsurface.h
split/kernel_lamp_emission.h
split/kernel_next_iteration_setup.h
+ split/kernel_path_init.h
+ split/kernel_queue_enqueue.h
split/kernel_scene_intersect.h
split/kernel_shader_eval.h
- split/kernel_shadow_blocked.h
+ split/kernel_shadow_blocked_ao.h
+ split/kernel_shadow_blocked_dl.h
split/kernel_split_common.h
- split/kernel_sum_all_radiance.h
+ split/kernel_split_data.h
+ split/kernel_split_data_types.h
+ split/kernel_subsurface_scatter.h
)
# CUDA module
@@ -227,8 +247,9 @@ if(WITH_CYCLES_CUDA_BINARIES)
endif()
# build for each arch
- set(cuda_sources kernels/cuda/kernel.cu
+ set(cuda_sources kernels/cuda/kernel.cu kernels/cuda/kernel_split.cu
${SRC_HEADERS}
+ ${SRC_KERNELS_CUDA_HEADERS}
${SRC_BVH_HEADERS}
${SRC_SVM_HEADERS}
${SRC_GEOM_HEADERS}
@@ -237,15 +258,22 @@ if(WITH_CYCLES_CUDA_BINARIES)
)
set(cuda_cubins)
- macro(CYCLES_CUDA_KERNEL_ADD arch experimental)
- if(${experimental})
- set(cuda_extra_flags "-D__KERNEL_EXPERIMENTAL__")
- set(cuda_cubin kernel_experimental_${arch}.cubin)
+ macro(CYCLES_CUDA_KERNEL_ADD arch split experimental)
+ if(${split})
+ set(cuda_extra_flags "-D__SPLIT__")
+ set(cuda_cubin kernel_split)
else()
set(cuda_extra_flags "")
- set(cuda_cubin kernel_${arch}.cubin)
+ set(cuda_cubin kernel)
endif()
+ if(${experimental})
+ set(cuda_extra_flags ${cuda_extra_flags} -D__KERNEL_EXPERIMENTAL__)
+ set(cuda_cubin ${cuda_cubin}_experimental)
+ endif()
+
+ set(cuda_cubin ${cuda_cubin}_${arch}.cubin)
+
if(WITH_CYCLES_DEBUG)
set(cuda_debug_flags "-D__KERNEL_DEBUG__")
else()
@@ -258,13 +286,19 @@ if(WITH_CYCLES_CUDA_BINARIES)
set(cuda_version_flags "-D__KERNEL_CUDA_VERSION__=${cuda_nvcc_version}")
set(cuda_math_flags "--use_fast_math")
+ if(split)
+ set(cuda_kernel_src "/kernels/cuda/kernel_split.cu")
+ else()
+ set(cuda_kernel_src "/kernels/cuda/kernel.cu")
+ endif()
+
add_custom_command(
OUTPUT ${cuda_cubin}
COMMAND ${cuda_nvcc_command}
-arch=${arch}
${CUDA_NVCC_FLAGS}
-m${CUDA_BITS}
- --cubin ${CMAKE_CURRENT_SOURCE_DIR}/kernels/cuda/kernel.cu
+ --cubin ${CMAKE_CURRENT_SOURCE_DIR}${cuda_kernel_src}
-o ${CMAKE_CURRENT_BINARY_DIR}/${cuda_cubin}
--ptxas-options="-v"
${cuda_arch_flags}
@@ -272,8 +306,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
${cuda_math_flags}
${cuda_extra_flags}
${cuda_debug_flags}
- -I${CMAKE_CURRENT_SOURCE_DIR}/../util
- -I${CMAKE_CURRENT_SOURCE_DIR}/svm
+ -I${CMAKE_CURRENT_SOURCE_DIR}/..
-DCCL_NAMESPACE_BEGIN=
-DCCL_NAMESPACE_END=
-DNVCC
@@ -291,7 +324,12 @@ if(WITH_CYCLES_CUDA_BINARIES)
foreach(arch ${CYCLES_CUDA_BINARIES_ARCH})
# Compile regular kernel
- CYCLES_CUDA_KERNEL_ADD(${arch} FALSE)
+ CYCLES_CUDA_KERNEL_ADD(${arch} FALSE FALSE)
+
+ if(WITH_CYCLES_CUDA_SPLIT_KERNEL_BINARIES)
+ # Compile split kernel
+ CYCLES_CUDA_KERNEL_ADD(${arch} TRUE FALSE)
+ endif()
endforeach()
add_custom_target(cycles_kernel_cuda ALL DEPENDS ${cuda_cubins})
@@ -309,36 +347,50 @@ endif()
include_directories(${INC})
include_directories(SYSTEM ${INC_SYS})
+set_source_files_properties(kernels/cpu/kernel.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
+set_source_files_properties(kernels/cpu/kernel_split.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_KERNEL_FLAGS}")
+
if(CXX_HAS_SSE)
list(APPEND SRC
kernels/cpu/kernel_sse2.cpp
kernels/cpu/kernel_sse3.cpp
kernels/cpu/kernel_sse41.cpp
+ kernels/cpu/kernel_split_sse2.cpp
+ kernels/cpu/kernel_split_sse3.cpp
+ kernels/cpu/kernel_split_sse41.cpp
)
set_source_files_properties(kernels/cpu/kernel_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
set_source_files_properties(kernels/cpu/kernel_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse3.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE3_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_sse41.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_SSE41_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX)
list(APPEND SRC
kernels/cpu/kernel_avx.cpp
+ kernels/cpu/kernel_split_avx.cpp
)
set_source_files_properties(kernels/cpu/kernel_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_avx.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX_KERNEL_FLAGS}")
endif()
if(CXX_HAS_AVX2)
list(APPEND SRC
kernels/cpu/kernel_avx2.cpp
+ kernels/cpu/kernel_split_avx2.cpp
)
set_source_files_properties(kernels/cpu/kernel_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
+ set_source_files_properties(kernels/cpu/kernel_split_avx2.cpp PROPERTIES COMPILE_FLAGS "${CYCLES_AVX2_KERNEL_FLAGS}")
endif()
add_library(cycles_kernel
${SRC}
${SRC_HEADERS}
${SRC_KERNELS_CPU_HEADERS}
+ ${SRC_KERNELS_CUDA_HEADERS}
${SRC_BVH_HEADERS}
${SRC_CLOSURE_HEADERS}
${SRC_SVM_HEADERS}
@@ -360,24 +412,33 @@ endif()
#add_custom_target(cycles_kernel_preprocess ALL DEPENDS ${KERNEL_PREPROCESSED})
#delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${KERNEL_PREPROCESSED}" ${CYCLES_INSTALL_PATH}/kernel)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_data_init.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_queue_enqueue.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_intersect.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_background_buffer_update.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_sum_all_radiance.cl" ${CYCLES_INSTALL_PATH}/kernel/kernels/opencl)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/kernel/kernels/cuda)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_BVH_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/bvh)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/closure)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/svm)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/geom)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel)
-delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SPLIT_HEADERS}" ${CYCLES_INSTALL_PATH}/kernel/split)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_state_buffer_size.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_split.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_data_init.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_path_init.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_queue_enqueue.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_scene_intersect.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_lamp_emission.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_do_volume.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_background.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shader_eval.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_subsurface_scatter.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_direct_lighting.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_ao.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_shadow_blocked_dl.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_next_iteration_setup.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_indirect_subsurface.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/opencl/kernel_buffer_update.cl" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/opencl)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "kernels/cuda/kernel_split.cu" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNELS_CUDA_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/kernels/cuda)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_BVH_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/bvh)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_CLOSURE_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/closure)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SVM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/svm)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_GEOM_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/geom)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/util)
+delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_SPLIT_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/split)
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index 36798982653..85741016b25 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -27,43 +27,43 @@
CCL_NAMESPACE_BEGIN
-#include "bvh_types.h"
+#include "kernel/bvh/bvh_types.h"
/* Common QBVH functions. */
#ifdef __QBVH__
-# include "qbvh_nodes.h"
+# include "kernel/bvh/qbvh_nodes.h"
#endif
/* Regular BVH traversal */
-#include "bvh_nodes.h"
+#include "kernel/bvh/bvh_nodes.h"
#define BVH_FUNCTION_NAME bvh_intersect
#define BVH_FUNCTION_FEATURES 0
-#include "bvh_traversal.h"
+#include "kernel/bvh/bvh_traversal.h"
#if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "bvh_traversal.h"
+# include "kernel/bvh/bvh_traversal.h"
#endif
#if defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_hair
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH
-# include "bvh_traversal.h"
+# include "kernel/bvh/bvh_traversal.h"
#endif
#if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "bvh_traversal.h"
+# include "kernel/bvh/bvh_traversal.h"
#endif
#if defined(__HAIR__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_hair_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_HAIR_MINIMUM_WIDTH|BVH_MOTION
-# include "bvh_traversal.h"
+# include "kernel/bvh/bvh_traversal.h"
#endif
/* Subsurface scattering BVH traversal */
@@ -71,12 +71,12 @@ CCL_NAMESPACE_BEGIN
#if defined(__SUBSURFACE__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface
# define BVH_FUNCTION_FEATURES BVH_HAIR
-# include "bvh_subsurface.h"
+# include "kernel/bvh/bvh_subsurface.h"
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_subsurface_motion
# define BVH_FUNCTION_FEATURES BVH_MOTION|BVH_HAIR
-# include "bvh_subsurface.h"
+# include "kernel/bvh/bvh_subsurface.h"
# endif
#endif /* __SUBSURFACE__ */
@@ -85,18 +85,18 @@ CCL_NAMESPACE_BEGIN
#if defined(__VOLUME__)
# define BVH_FUNCTION_NAME bvh_intersect_volume
# define BVH_FUNCTION_FEATURES BVH_HAIR
-# include "bvh_volume.h"
+# include "kernel/bvh/bvh_volume.h"
# if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_volume.h"
+# include "kernel/bvh/bvh_volume.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
-# include "bvh_volume.h"
+# include "kernel/bvh/bvh_volume.h"
# endif
#endif /* __VOLUME__ */
@@ -105,30 +105,30 @@ CCL_NAMESPACE_BEGIN
#if defined(__SHADOW_RECORD_ALL__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all
# define BVH_FUNCTION_FEATURES 0
-# include "bvh_shadow_all.h"
+# include "kernel/bvh/bvh_shadow_all.h"
# if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING
-# include "bvh_shadow_all.h"
+# include "kernel/bvh/bvh_shadow_all.h"
# endif
# if defined(__HAIR__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_shadow_all.h"
+# include "kernel/bvh/bvh_shadow_all.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION
-# include "bvh_shadow_all.h"
+# include "kernel/bvh/bvh_shadow_all.h"
# endif
# if defined(__HAIR__) && defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_shadow_all_hair_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR|BVH_MOTION
-# include "bvh_shadow_all.h"
+# include "kernel/bvh/bvh_shadow_all.h"
# endif
#endif /* __SHADOW_RECORD_ALL__ */
@@ -137,18 +137,18 @@ CCL_NAMESPACE_BEGIN
#if defined(__VOLUME_RECORD_ALL__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all
# define BVH_FUNCTION_FEATURES BVH_HAIR
-# include "bvh_volume_all.h"
+# include "kernel/bvh/bvh_volume_all.h"
# if defined(__INSTANCING__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_instancing
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_HAIR
-# include "bvh_volume_all.h"
+# include "kernel/bvh/bvh_volume_all.h"
# endif
# if defined(__OBJECT_MOTION__)
# define BVH_FUNCTION_NAME bvh_intersect_volume_all_motion
# define BVH_FUNCTION_FEATURES BVH_INSTANCING|BVH_MOTION|BVH_HAIR
-# include "bvh_volume_all.h"
+# include "kernel/bvh/bvh_volume_all.h"
# endif
#endif /* __VOLUME_RECORD_ALL__ */
@@ -202,8 +202,9 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
}
#ifdef __SUBSURFACE__
+/* Note: ray is passed by value to work around a possible CUDA compiler bug. */
ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
- const Ray *ray,
+ const Ray ray,
SubsurfaceIntersection *ss_isect,
int subsurface_object,
uint *lcg_state,
@@ -212,7 +213,7 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
#ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
return bvh_intersect_subsurface_motion(kg,
- ray,
+ &ray,
ss_isect,
subsurface_object,
lcg_state,
@@ -220,7 +221,7 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
}
#endif /* __OBJECT_MOTION__ */
return bvh_intersect_subsurface(kg,
- ray,
+ &ray,
ss_isect,
subsurface_object,
lcg_state,
@@ -229,30 +230,63 @@ ccl_device_intersect void scene_intersect_subsurface(KernelGlobals *kg,
#endif
#ifdef __SHADOW_RECORD_ALL__
-ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg, const Ray *ray, Intersection *isect, uint max_hits, uint *num_hits)
+ccl_device_intersect bool scene_intersect_shadow_all(KernelGlobals *kg,
+ const Ray *ray,
+ Intersection *isect,
+ int skip_object,
+ uint max_hits,
+ uint *num_hits)
{
# ifdef __OBJECT_MOTION__
if(kernel_data.bvh.have_motion) {
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_shadow_all_hair_motion(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair_motion(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __HAIR__ */
- return bvh_intersect_shadow_all_motion(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_shadow_all_motion(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
}
# endif /* __OBJECT_MOTION__ */
# ifdef __HAIR__
- if(kernel_data.bvh.have_curves)
- return bvh_intersect_shadow_all_hair(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_curves) {
+ return bvh_intersect_shadow_all_hair(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __HAIR__ */
# ifdef __INSTANCING__
- if(kernel_data.bvh.have_instancing)
- return bvh_intersect_shadow_all_instancing(kg, ray, isect, max_hits, num_hits);
+ if(kernel_data.bvh.have_instancing) {
+ return bvh_intersect_shadow_all_instancing(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
+ }
# endif /* __INSTANCING__ */
- return bvh_intersect_shadow_all(kg, ray, isect, max_hits, num_hits);
+ return bvh_intersect_shadow_all(kg,
+ ray,
+ isect,
+ skip_object,
+ max_hits,
+ num_hits);
}
#endif /* __SHADOW_RECORD_ALL__ */
@@ -357,7 +391,7 @@ ccl_device_inline float3 ray_offset(float3 P, float3 Ng)
#endif
}
-#if defined(__SHADOW_RECORD_ALL__) || defined (__VOLUME_RECORD_ALL__)
+#if defined(__VOLUME_RECORD_ALL__) || (defined(__SHADOW_RECORD_ALL__) && defined(__KERNEL_CPU__))
/* ToDo: Move to another file? */
ccl_device int intersections_compare(const void *a, const void *b)
{
@@ -373,5 +407,28 @@ ccl_device int intersections_compare(const void *a, const void *b)
}
#endif
-CCL_NAMESPACE_END
+#if defined(__SHADOW_RECORD_ALL__)
+ccl_device_inline void sort_intersections(Intersection *hits, uint num_hits)
+{
+#ifdef __KERNEL_GPU__
+ /* Use bubble sort which has more friendly memory pattern on GPU. */
+ bool swapped;
+ do {
+ swapped = false;
+ for(int j = 0; j < num_hits - 1; ++j) {
+ if(hits[j].t > hits[j + 1].t) {
+ struct Intersection tmp = hits[j];
+ hits[j] = hits[j + 1];
+ hits[j + 1] = tmp;
+ swapped = true;
+ }
+ }
+ --num_hits;
+ } while(swapped);
+#else
+ qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
+#endif
+}
+#endif /* __SHADOW_RECORD_ALL__ | __VOLUME_RECORD_ALL__ */
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/bvh/bvh_nodes.h b/intern/cycles/kernel/bvh/bvh_nodes.h
index 726bef1794c..74a9ebf14e4 100644
--- a/intern/cycles/kernel/bvh/bvh_nodes.h
+++ b/intern/cycles/kernel/bvh/bvh_nodes.h
@@ -17,8 +17,8 @@
// TODO(sergey): Look into avoid use of full Transform and use 3x3 matrix and
// 3-vector which might be faster.
ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *kg,
- int node_addr,
- int child)
+ int node_addr,
+ int child)
{
Transform space;
const int child_addr = node_addr + child * 3;
@@ -31,12 +31,12 @@ ccl_device_forceinline Transform bvh_unaligned_node_fetch_space(KernelGlobals *k
#if !defined(__KERNEL_SSE2__)
ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg,
- const float3 P,
- const float3 idir,
- const float t,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
/* fetch node data */
@@ -78,14 +78,14 @@ ccl_device_forceinline int bvh_aligned_node_intersect(KernelGlobals *kg,
}
ccl_device_forceinline int bvh_aligned_node_intersect_robust(KernelGlobals *kg,
- const float3 P,
- const float3 idir,
- const float t,
- const float difl,
- const float extmax,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
/* fetch node data */
@@ -203,13 +203,13 @@ ccl_device_forceinline bool bvh_unaligned_node_intersect_child_robust(
}
ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float3 idir,
- const float t,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
int mask = 0;
float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
@@ -233,15 +233,15 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
}
ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float3 idir,
- const float t,
- const float difl,
- const float extmax,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
int mask = 0;
float4 cnodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
@@ -265,13 +265,13 @@ ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg
}
ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float3 idir,
- const float t,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
@@ -296,15 +296,15 @@ ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
}
ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const float3 idir,
- const float t,
- const float difl,
- const float extmax,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const float3 idir,
+ const float t,
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
@@ -442,19 +442,19 @@ ccl_device_forceinline int bvh_aligned_node_intersect_robust(
}
ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const ssef& isect_near,
+ const ssef& isect_far,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
float3 aligned_dir0 = transform_direction(&space0, dir),
- aligned_dir1 = transform_direction(&space1, dir);;
+ aligned_dir1 = transform_direction(&space1, dir);
float3 aligned_P0 = transform_point(&space0, P),
aligned_P1 = transform_point(&space1, P);
float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
@@ -503,20 +503,20 @@ ccl_device_forceinline int bvh_unaligned_node_intersect(KernelGlobals *kg,
}
ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg,
- const float3 P,
- const float3 dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const float difl,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3 P,
+ const float3 dir,
+ const ssef& isect_near,
+ const ssef& isect_far,
+ const float difl,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
Transform space0 = bvh_unaligned_node_fetch_space(kg, node_addr, 0);
Transform space1 = bvh_unaligned_node_fetch_space(kg, node_addr, 1);
float3 aligned_dir0 = transform_direction(&space0, dir),
- aligned_dir1 = transform_direction(&space1, dir);;
+ aligned_dir1 = transform_direction(&space1, dir);
float3 aligned_P0 = transform_point(&space0, P),
aligned_P1 = transform_point(&space1, P);
float3 nrdir0 = -bvh_inverse_direction(aligned_dir0),
@@ -574,17 +574,17 @@ ccl_device_forceinline int bvh_unaligned_node_intersect_robust(KernelGlobals *kg
}
ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const ssef& tsplat,
- const ssef Psplat[3],
- const ssef idirsplat[3],
- const shuffle_swap_t shufflexyz[3],
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3& P,
+ const float3& dir,
+ const ssef& isect_near,
+ const ssef& isect_far,
+ const ssef& tsplat,
+ const ssef Psplat[3],
+ const ssef idirsplat[3],
+ const shuffle_swap_t shufflexyz[3],
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
@@ -612,19 +612,19 @@ ccl_device_forceinline int bvh_node_intersect(KernelGlobals *kg,
}
ccl_device_forceinline int bvh_node_intersect_robust(KernelGlobals *kg,
- const float3& P,
- const float3& dir,
- const ssef& isect_near,
- const ssef& isect_far,
- const ssef& tsplat,
- const ssef Psplat[3],
- const ssef idirsplat[3],
- const shuffle_swap_t shufflexyz[3],
- const float difl,
- const float extmax,
- const int node_addr,
- const uint visibility,
- float dist[2])
+ const float3& P,
+ const float3& dir,
+ const ssef& isect_near,
+ const ssef& isect_far,
+ const ssef& tsplat,
+ const ssef Psplat[3],
+ const ssef idirsplat[3],
+ const shuffle_swap_t shufflexyz[3],
+ const float difl,
+ const float extmax,
+ const int node_addr,
+ const uint visibility,
+ float dist[2])
{
float4 node = kernel_tex_fetch(__bvh_nodes, node_addr);
if(__float_as_uint(node.x) & PATH_RAY_NODE_UNALIGNED) {
diff --git a/intern/cycles/kernel/bvh/bvh_shadow_all.h b/intern/cycles/kernel/bvh/bvh_shadow_all.h
index df33a86bb18..267e098f912 100644
--- a/intern/cycles/kernel/bvh/bvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/bvh_shadow_all.h
@@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
-# include "qbvh_shadow_all.h"
+# include "kernel/bvh/qbvh_shadow_all.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -45,6 +45,7 @@ ccl_device_inline
bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -100,9 +101,6 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif /* __KERNEL_SSE2__ */
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* traversal loop */
do {
do {
@@ -189,6 +187,16 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+#ifdef __SHADOW_TRICKS__
+ uint tri_object = (object == OBJECT_NONE)
+ ? kernel_tex_fetch(__prim_object, prim_addr)
+ : object;
+ if(tri_object == skip_object) {
+ ++prim_addr;
+ continue;
+ }
+#endif
+
bool hit;
/* todo: specialized intersect functions which don't fill in
@@ -198,9 +206,9 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg,
- &isect_precalc,
isect_array,
P,
+ dir,
PATH_RAY_SHADOW,
object,
prim_addr);
@@ -309,12 +317,11 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
isect_array->t = isect_t;
@@ -354,22 +361,17 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* scale isect->t to adjust for instancing */
for(int i = 0; i < num_hits_in_instance; i++) {
(isect_array-i-1)->t *= t_fac;
}
}
else {
- float ignore_t = FLT_MAX;
-
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
}
isect_t = tmax;
@@ -400,6 +402,7 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -408,6 +411,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
ray,
isect_array,
+ skip_object,
max_hits,
num_hits);
}
@@ -418,6 +422,7 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
return BVH_FUNCTION_FULL_NAME(BVH)(kg,
ray,
isect_array,
+ skip_object,
max_hits,
num_hits);
}
diff --git a/intern/cycles/kernel/bvh/bvh_subsurface.h b/intern/cycles/kernel/bvh/bvh_subsurface.h
index 889bbca21e2..bda7e34907a 100644
--- a/intern/cycles/kernel/bvh/bvh_subsurface.h
+++ b/intern/cycles/kernel/bvh/bvh_subsurface.h
@@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
-# include "qbvh_subsurface.h"
+# include "kernel/bvh/qbvh_subsurface.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -75,16 +75,16 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
Transform ob_itfm;
- bvh_instance_motion_push(kg,
- subsurface_object,
- ray,
- &P,
- &dir,
- &idir,
- &isect_t,
- &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg,
+ subsurface_object,
+ ray,
+ &P,
+ &dir,
+ &idir,
+ isect_t,
+ &ob_itfm);
#else
- bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
#endif
object = subsurface_object;
}
@@ -109,9 +109,6 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* traversal loop */
do {
do {
@@ -197,9 +194,9 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
- &isect_precalc,
ss_isect,
P,
+ dir,
object,
prim_addr,
isect_t,
diff --git a/intern/cycles/kernel/bvh/bvh_traversal.h b/intern/cycles/kernel/bvh/bvh_traversal.h
index 80c8f31473a..c58d3b0316c 100644
--- a/intern/cycles/kernel/bvh/bvh_traversal.h
+++ b/intern/cycles/kernel/bvh/bvh_traversal.h
@@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
-# include "qbvh_traversal.h"
+# include "kernel/bvh/qbvh_traversal.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -104,9 +104,6 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* traversal loop */
do {
do {
@@ -238,9 +235,9 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(triangle_intersect(kg,
- &isect_precalc,
isect,
P,
+ dir,
visibility,
object,
prim_addr))
@@ -354,11 +351,10 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
# if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
@@ -391,11 +387,10 @@ ccl_device_noinline bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* instance pop */
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
# if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
diff --git a/intern/cycles/kernel/bvh/bvh_volume.h b/intern/cycles/kernel/bvh/bvh_volume.h
index 57e5b8d736d..764aaee44a1 100644
--- a/intern/cycles/kernel/bvh/bvh_volume.h
+++ b/intern/cycles/kernel/bvh/bvh_volume.h
@@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
-# include "qbvh_volume.h"
+# include "kernel/bvh/qbvh_volume.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -97,9 +97,6 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* traversal loop */
do {
do {
@@ -194,9 +191,9 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
continue;
}
triangle_intersect(kg,
- &isect_precalc,
isect,
P,
+ dir,
visibility,
object,
prim_addr);
@@ -238,13 +235,11 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
# if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
@@ -281,13 +276,11 @@ bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* instance pop */
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
# if defined(__KERNEL_SSE2__)
Psplat[0] = ssef(P.x);
Psplat[1] = ssef(P.y);
diff --git a/intern/cycles/kernel/bvh/bvh_volume_all.h b/intern/cycles/kernel/bvh/bvh_volume_all.h
index 5a1accebaa0..04ec334e54d 100644
--- a/intern/cycles/kernel/bvh/bvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/bvh_volume_all.h
@@ -18,7 +18,7 @@
*/
#ifdef __QBVH__
-# include "qbvh_volume_all.h"
+# include "kernel/bvh/qbvh_volume_all.h"
#endif
#if BVH_FEATURE(BVH_HAIR)
@@ -101,9 +101,6 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
gen_idirsplat_swap(pn, shuf_identity, shuf_swap, idir, idirsplat, shufflexyz);
#endif /* __KERNEL_SSE2__ */
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* traversal loop */
do {
do {
@@ -199,9 +196,9 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
continue;
}
hit = triangle_intersect(kg,
- &isect_precalc,
isect_array,
P,
+ dir,
visibility,
object,
prim_addr);
@@ -288,14 +285,12 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
object = kernel_tex_fetch(__prim_object, -prim_addr-1);
int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) {
-
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
isect_array->t = isect_t;
@@ -341,20 +336,17 @@ uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
# else
bvh_instance_pop_factor(kg, object, ray, &P, &dir, &idir, &t_fac);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
/* Scale isect->t to adjust for instancing. */
for(int i = 0; i < num_hits_in_instance; i++) {
(isect_array-i-1)->t *= t_fac;
}
}
else {
- float ignore_t = FLT_MAX;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
}
isect_t = tmax;
diff --git a/intern/cycles/kernel/bvh/qbvh_shadow_all.h b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
index 607295f9ed5..ce474438f2c 100644
--- a/intern/cycles/kernel/bvh/qbvh_shadow_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_shadow_all.h
@@ -33,6 +33,7 @@
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
Intersection *isect_array,
+ const int skip_object,
const uint max_hits,
uint *num_hits)
{
@@ -96,15 +97,13 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
&near_x, &near_y, &near_z,
&far_x, &far_y, &far_z);
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* Traversal loop. */
do {
do {
/* Traverse internal nodes. */
while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ (void)inodes;
if(false
#ifdef __VISIBILITY_FLAG__
@@ -270,6 +269,16 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
while(prim_addr < prim_addr2) {
kernel_assert((kernel_tex_fetch(__prim_type, prim_addr) & PRIMITIVE_ALL) == p_type);
+#ifdef __SHADOW_TRICKS__
+ uint tri_object = (object == OBJECT_NONE)
+ ? kernel_tex_fetch(__prim_object, prim_addr)
+ : object;
+ if(tri_object == skip_object) {
+ ++prim_addr;
+ continue;
+ }
+#endif
+
bool hit;
/* todo: specialized intersect functions which don't fill in
@@ -279,9 +288,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg,
- &isect_precalc,
isect_array,
P,
+ dir,
PATH_RAY_SHADOW,
object,
prim_addr);
@@ -390,9 +399,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
object = kernel_tex_fetch(__prim_object, -prim_addr-1);
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
num_hits_in_instance = 0;
@@ -414,8 +423,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
++stack_ptr;
kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
@@ -445,11 +452,10 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
}
}
else {
- float ignore_t = FLT_MAX;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
}
@@ -472,8 +478,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
object = OBJECT_NONE;
node_addr = traversal_stack[stack_ptr].addr;
--stack_ptr;
diff --git a/intern/cycles/kernel/bvh/qbvh_subsurface.h b/intern/cycles/kernel/bvh/qbvh_subsurface.h
index 84dc4003133..be7658d11d7 100644
--- a/intern/cycles/kernel/bvh/qbvh_subsurface.h
+++ b/intern/cycles/kernel/bvh/qbvh_subsurface.h
@@ -64,16 +64,16 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
#if BVH_FEATURE(BVH_MOTION)
Transform ob_itfm;
- bvh_instance_motion_push(kg,
- subsurface_object,
- ray,
- &P,
- &dir,
- &idir,
- &isect_t,
- &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg,
+ subsurface_object,
+ ray,
+ &P,
+ &dir,
+ &idir,
+ isect_t,
+ &ob_itfm);
#else
- bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, subsurface_object, ray, &P, &dir, &idir, isect_t);
#endif
object = subsurface_object;
}
@@ -105,9 +105,6 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
&near_x, &near_y, &near_z,
&far_x, &far_y, &far_z);
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* Traversal loop. */
do {
do {
@@ -253,9 +250,9 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_subsurface(kg,
- &isect_precalc,
ss_isect,
P,
+ dir,
object,
prim_addr,
isect_t,
diff --git a/intern/cycles/kernel/bvh/qbvh_traversal.h b/intern/cycles/kernel/bvh/qbvh_traversal.h
index 10ae7bee852..fca75a1d416 100644
--- a/intern/cycles/kernel/bvh/qbvh_traversal.h
+++ b/intern/cycles/kernel/bvh/qbvh_traversal.h
@@ -106,15 +106,13 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
&near_x, &near_y, &near_z,
&far_x, &far_y, &far_z);
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* Traversal loop. */
do {
do {
/* Traverse internal nodes. */
while(node_addr >= 0 && node_addr != ENTRYPOINT_SENTINEL) {
float4 inodes = kernel_tex_fetch(__bvh_nodes, node_addr+0);
+ (void)inodes;
if(UNLIKELY(node_dist > isect->t)
#if BVH_FEATURE(BVH_MOTION)
@@ -122,8 +120,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
|| UNLIKELY(ray->time > inodes.z)
#endif
#ifdef __VISIBILITY_FLAG__
- || (__float_as_uint(inodes.x) & visibility) == 0)
+ || (__float_as_uint(inodes.x) & visibility) == 0
#endif
+ )
{
/* Pop. */
node_addr = traversal_stack[stack_ptr].addr;
@@ -333,9 +332,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
BVH_DEBUG_NEXT_INTERSECTION();
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
if(triangle_intersect(kg,
- &isect_precalc,
isect,
P,
+ dir,
visibility,
object,
prim_addr)) {
@@ -447,8 +446,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
++stack_ptr;
kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
@@ -468,9 +465,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
qbvh_near_far_idx_calc(idir,
@@ -489,8 +486,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
object = OBJECT_NONE;
node_addr = traversal_stack[stack_ptr].addr;
node_dist = traversal_stack[stack_ptr].dist;
diff --git a/intern/cycles/kernel/bvh/qbvh_volume.h b/intern/cycles/kernel/bvh/qbvh_volume.h
index dc6627e2dbb..192ce009524 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume.h
@@ -91,9 +91,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
&near_x, &near_y, &near_z,
&far_x, &far_y, &far_z);
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* Traversal loop. */
do {
do {
@@ -266,7 +263,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
continue;
}
/* Intersect ray against primitive. */
- triangle_intersect(kg, &isect_precalc, isect, P, visibility, object, prim_addr);
+ triangle_intersect(kg, isect, P, dir, visibility, object, prim_addr);
}
break;
}
@@ -295,9 +292,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
qbvh_near_far_idx_calc(idir,
@@ -316,8 +313,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
++stack_ptr;
kernel_assert(stack_ptr < BVH_QSTACK_SIZE);
traversal_stack[stack_ptr].addr = ENTRYPOINT_SENTINEL;
@@ -341,9 +336,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Instance pop. */
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &isect->t, &ob_itfm);
+ isect->t = bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, isect->t, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &isect->t);
+ isect->t = bvh_instance_pop(kg, object, ray, &P, &dir, &idir, isect->t);
# endif
qbvh_near_far_idx_calc(idir,
@@ -362,8 +357,6 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
object = OBJECT_NONE;
node_addr = traversal_stack[stack_ptr].addr;
--stack_ptr;
diff --git a/intern/cycles/kernel/bvh/qbvh_volume_all.h b/intern/cycles/kernel/bvh/qbvh_volume_all.h
index ff1fa92af6e..ac5f58a9a51 100644
--- a/intern/cycles/kernel/bvh/qbvh_volume_all.h
+++ b/intern/cycles/kernel/bvh/qbvh_volume_all.h
@@ -95,9 +95,6 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
&near_x, &near_y, &near_z,
&far_x, &far_y, &far_z);
- IsectPrecalc isect_precalc;
- triangle_intersect_precalc(dir, &isect_precalc);
-
/* Traversal loop. */
do {
do {
@@ -271,7 +268,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
continue;
}
/* Intersect ray against primitive. */
- hit = triangle_intersect(kg, &isect_precalc, isect_array, P, visibility, object, prim_addr);
+ hit = triangle_intersect(kg, isect_array, P, dir, visibility, object, prim_addr);
if(hit) {
/* Move on to next entry in intersections array. */
isect_array++;
@@ -346,9 +343,9 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int object_flag = kernel_tex_fetch(__object_flag, object);
if(object_flag & SD_OBJECT_HAS_VOLUME) {
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, &isect_t, &ob_itfm);
+ isect_t = bvh_instance_motion_push(kg, object, ray, &P, &dir, &idir, isect_t, &ob_itfm);
# else
- bvh_instance_push(kg, object, ray, &P, &dir, &idir, &isect_t);
+ isect_t = bvh_instance_push(kg, object, ray, &P, &dir, &idir, isect_t);
# endif
qbvh_near_far_idx_calc(idir,
@@ -367,7 +364,6 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
num_hits_in_instance = 0;
isect_array->t = isect_t;
@@ -406,11 +402,10 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
}
}
else {
- float ignore_t = FLT_MAX;
# if BVH_FEATURE(BVH_MOTION)
- bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, &ignore_t, &ob_itfm);
+ bvh_instance_motion_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX, &ob_itfm);
# else
- bvh_instance_pop(kg, object, ray, &P, &dir, &idir, &ignore_t);
+ bvh_instance_pop(kg, object, ray, &P, &dir, &idir, FLT_MAX);
# endif
}
@@ -433,8 +428,6 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
org4 = sse3f(ssef(P.x), ssef(P.y), ssef(P.z));
# endif
- triangle_intersect_precalc(dir, &isect_precalc);
-
object = OBJECT_NONE;
node_addr = traversal_stack[stack_ptr].addr;
--stack_ptr;
diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h
index b7abc1ec507..e799855a65e 100644
--- a/intern/cycles/kernel/closure/alloc.h
+++ b/intern/cycles/kernel/closure/alloc.h
@@ -20,17 +20,17 @@ ccl_device ShaderClosure *closure_alloc(ShaderData *sd, int size, ClosureType ty
{
kernel_assert(size <= sizeof(ShaderClosure));
- int num_closure = ccl_fetch(sd, num_closure);
- int num_closure_extra = ccl_fetch(sd, num_closure_extra);
+ int num_closure = sd->num_closure;
+ int num_closure_extra = sd->num_closure_extra;
if(num_closure + num_closure_extra >= MAX_CLOSURE)
return NULL;
- ShaderClosure *sc = &ccl_fetch(sd, closure)[num_closure];
+ ShaderClosure *sc = &sd->closure[num_closure];
sc->type = type;
sc->weight = weight;
- ccl_fetch(sd, num_closure)++;
+ sd->num_closure++;
return sc;
}
@@ -44,25 +44,25 @@ ccl_device ccl_addr_space void *closure_alloc_extra(ShaderData *sd, int size)
* This lets us keep the same fast array iteration over closures, as we
* found linked list iteration and iteration with skipping to be slower. */
int num_extra = ((size + sizeof(ShaderClosure) - 1) / sizeof(ShaderClosure));
- int num_closure = ccl_fetch(sd, num_closure);
- int num_closure_extra = ccl_fetch(sd, num_closure_extra) + num_extra;
+ int num_closure = sd->num_closure;
+ int num_closure_extra = sd->num_closure_extra + num_extra;
if(num_closure + num_closure_extra > MAX_CLOSURE) {
/* Remove previous closure. */
- ccl_fetch(sd, num_closure)--;
- ccl_fetch(sd, num_closure_extra)++;
+ sd->num_closure--;
+ sd->num_closure_extra++;
return NULL;
}
- ccl_fetch(sd, num_closure_extra) = num_closure_extra;
- return (ccl_addr_space void*)(ccl_fetch(sd, closure) + MAX_CLOSURE - num_closure_extra);
+ sd->num_closure_extra = num_closure_extra;
+ return (ccl_addr_space void*)(sd->closure + MAX_CLOSURE - num_closure_extra);
}
ccl_device_inline ShaderClosure *bsdf_alloc(ShaderData *sd, int size, float3 weight)
{
ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight);
- if(!sc)
+ if(sc == NULL)
return NULL;
float sample_weight = fabsf(average(weight));
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index 7e4d5fe2e37..9139b99353a 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -14,126 +14,126 @@
* limitations under the License.
*/
-#include "../closure/bsdf_ashikhmin_velvet.h"
-#include "../closure/bsdf_diffuse.h"
-#include "../closure/bsdf_oren_nayar.h"
-#include "../closure/bsdf_phong_ramp.h"
-#include "../closure/bsdf_diffuse_ramp.h"
-#include "../closure/bsdf_microfacet.h"
-#include "../closure/bsdf_microfacet_multi.h"
-#include "../closure/bsdf_reflection.h"
-#include "../closure/bsdf_refraction.h"
-#include "../closure/bsdf_transparent.h"
-#include "../closure/bsdf_ashikhmin_shirley.h"
-#include "../closure/bsdf_toon.h"
-#include "../closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_ashikhmin_velvet.h"
+#include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bsdf_oren_nayar.h"
+#include "kernel/closure/bsdf_phong_ramp.h"
+#include "kernel/closure/bsdf_diffuse_ramp.h"
+#include "kernel/closure/bsdf_microfacet.h"
+#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_reflection.h"
+#include "kernel/closure/bsdf_refraction.h"
+#include "kernel/closure/bsdf_transparent.h"
+#include "kernel/closure/bsdf_ashikhmin_shirley.h"
+#include "kernel/closure/bsdf_toon.h"
+#include "kernel/closure/bsdf_hair.h"
#ifdef __SUBSURFACE__
-# include "../closure/bssrdf.h"
+# include "kernel/closure/bssrdf.h"
#endif
#ifdef __VOLUME__
-# include "../closure/volume.h"
+# include "kernel/closure/volume.h"
#endif
CCL_NAMESPACE_BEGIN
ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
- ShaderData *sd,
- const ShaderClosure *sc,
- float randu,
- float randv,
- float3 *eval,
- float3 *omega_in,
- differential3 *domega_in,
- float *pdf)
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ float randu,
+ float randv,
+ float3 *eval,
+ float3 *omega_in,
+ differential3 *domega_in,
+ float *pdf)
{
int label;
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- label = bsdf_diffuse_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- label = bsdf_oren_nayar_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
- label = bsdf_phong_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- label = bsdf_diffuse_ramp_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
- label = bsdf_translucent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- label = bsdf_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- label = bsdf_refraction_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- label = bsdf_transparent_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- label = bsdf_microfacet_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- label = bsdf_microfacet_multi_ggx_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
+ label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
- eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &ccl_fetch(sd, lcg_state));
+ label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+ eval, omega_in, &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- label = bsdf_microfacet_beckmann_sample(kg, sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_microfacet_beckmann_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- label = bsdf_ashikhmin_shirley_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_ashikhmin_shirley_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- label = bsdf_ashikhmin_velvet_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- label = bsdf_diffuse_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_diffuse_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- label = bsdf_glossy_toon_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_glossy_toon_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- label = bsdf_hair_reflection_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_hair_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- label = bsdf_hair_transmission_sample(sc, ccl_fetch(sd, Ng), ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv,
+ label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- label = volume_henyey_greenstein_sample(sc, ccl_fetch(sd, I), ccl_fetch(sd, dI).dx, ccl_fetch(sd, dI).dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+ label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
break;
#endif
default:
@@ -157,75 +157,75 @@ float3 bsdf_eval(KernelGlobals *kg,
{
float3 eval;
- if(dot(ccl_fetch(sd, Ng), omega_in) >= 0.0f) {
+ if(dot(sd->Ng, omega_in) >= 0.0f) {
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __OSL__
case CLOSURE_BSDF_PHONG_RAMP_ID:
- eval = bsdf_phong_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_RAMP_ID:
- eval = bsdf_diffuse_ramp_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_ashikhmin_shirley_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_diffuse_toon_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_glossy_toon_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_hair_reflection_eval_reflect(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_reflect(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
break;
#endif
default:
@@ -237,63 +237,63 @@ float3 bsdf_eval(KernelGlobals *kg,
switch(sc->type) {
case CLOSURE_BSDF_DIFFUSE_ID:
case CLOSURE_BSDF_BSSRDF_ID:
- eval = bsdf_diffuse_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
case CLOSURE_BSDF_OREN_NAYAR_ID:
- eval = bsdf_oren_nayar_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSLUCENT_ID:
- eval = bsdf_translucent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFLECTION_ID:
- eval = bsdf_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_REFRACTION_ID:
- eval = bsdf_refraction_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_TRANSPARENT_ID:
- eval = bsdf_transparent_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_GGX_ID:
case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
- eval = bsdf_microfacet_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
- eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
- eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf, &ccl_fetch(sd, lcg_state));
+ eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
break;
case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
- eval = bsdf_microfacet_beckmann_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID:
case CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID:
- eval = bsdf_ashikhmin_shirley_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_ashikhmin_shirley_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID:
- eval = bsdf_ashikhmin_velvet_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_DIFFUSE_TOON_ID:
- eval = bsdf_diffuse_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_diffuse_toon_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_GLOSSY_TOON_ID:
- eval = bsdf_glossy_toon_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_glossy_toon_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
- eval = bsdf_hair_reflection_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_hair_reflection_eval_transmit(sc, sd->I, omega_in, pdf);
break;
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
- eval = bsdf_hair_transmission_eval_transmit(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#endif
#ifdef __VOLUME__
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
- eval = volume_henyey_greenstein_eval_phase(sc, ccl_fetch(sd, I), omega_in, pdf);
+ eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
break;
#endif
default:
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h
index 4a1316fd2a9..1c7b3eb9ddd 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet.h
@@ -266,7 +266,7 @@ ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosur
(bsdf_a->alpha_y == bsdf_b->alpha_y) &&
(isequal_float3(bsdf_a->T, bsdf_b->T)) &&
(bsdf_a->ior == bsdf_b->ior) &&
- ((!bsdf_a->extra && !bsdf_b->extra) ||
+ ((bsdf_a->extra == NULL && bsdf_b->extra == NULL) ||
((bsdf_a->extra && bsdf_b->extra) &&
(isequal_float3(bsdf_a->extra->color, bsdf_b->extra->color))));
}
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
index cea59adfebe..7d87727004f 100644
--- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
+++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h
@@ -43,7 +43,7 @@ ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float2 randU)
{
if(cosI > 0.9999f || cosI < 1e-6f) {
- const float r = sqrtf(randU.x / (1.0f - randU.x));
+ const float r = sqrtf(randU.x / max(1.0f - randU.x, 1e-7f));
const float phi = M_2PI_F * randU.y;
return make_float2(r*cosf(phi), r*sinf(phi));
}
@@ -83,7 +83,7 @@ ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha
const float3 wi_11 = normalize(make_float3(alpha.x*wi.x, alpha.y*wi.y, wi.z));
const float2 slope_11 = mf_sampleP22_11(wi_11.z, randU);
- const float2 cossin_phi = normalize(make_float2(wi_11.x, wi_11.y));
+ const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
const float slope_x = alpha.x*(cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
const float slope_y = alpha.y*(cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
@@ -313,18 +313,18 @@ ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, cons
#define MF_PHASE_FUNCTION glass
#define MF_MULTI_GLASS
-#include "bsdf_microfacet_multi_impl.h"
+#include "kernel/closure/bsdf_microfacet_multi_impl.h"
/* The diffuse phase function is not implemented as a node yet. */
#if 0
#define MF_PHASE_FUNCTION diffuse
#define MF_MULTI_DIFFUSE
-#include "bsdf_microfacet_multi_impl.h"
+#include "kernel/closure/bsdf_microfacet_multi_impl.h"
#endif
#define MF_PHASE_FUNCTION glossy
#define MF_MULTI_GLOSSY
-#include "bsdf_microfacet_multi_impl.h"
+#include "kernel/closure/bsdf_microfacet_multi_impl.h"
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
{
diff --git a/intern/cycles/kernel/geom/geom.h b/intern/cycles/kernel/geom/geom.h
index 6838e26c242..c623e3490fd 100644
--- a/intern/cycles/kernel/geom/geom.h
+++ b/intern/cycles/kernel/geom/geom.h
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-#include "geom_attribute.h"
-#include "geom_object.h"
+#include "kernel/geom/geom_attribute.h"
+#include "kernel/geom/geom_object.h"
#ifdef __PATCH_EVAL__
-# include "geom_patch.h"
+# include "kernel/geom/geom_patch.h"
#endif
-#include "geom_triangle.h"
-#include "geom_subd_triangle.h"
-#include "geom_triangle_intersect.h"
-#include "geom_motion_triangle.h"
-#include "geom_motion_triangle_intersect.h"
-#include "geom_motion_triangle_shader.h"
-#include "geom_motion_curve.h"
-#include "geom_curve.h"
-#include "geom_volume.h"
-#include "geom_primitive.h"
+#include "kernel/geom/geom_triangle.h"
+#include "kernel/geom/geom_subd_triangle.h"
+#include "kernel/geom/geom_triangle_intersect.h"
+#include "kernel/geom/geom_motion_triangle.h"
+#include "kernel/geom/geom_motion_triangle_intersect.h"
+#include "kernel/geom/geom_motion_triangle_shader.h"
+#include "kernel/geom/geom_motion_curve.h"
+#include "kernel/geom/geom_curve.h"
+#include "kernel/geom/geom_volume.h"
+#include "kernel/geom/geom_primitive.h"
diff --git a/intern/cycles/kernel/geom/geom_attribute.h b/intern/cycles/kernel/geom/geom_attribute.h
index 08ccee56335..cc62192ef21 100644
--- a/intern/cycles/kernel/geom/geom_attribute.h
+++ b/intern/cycles/kernel/geom/geom_attribute.h
@@ -30,7 +30,7 @@ ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *
ccl_device_inline uint attribute_primitive_type(KernelGlobals *kg, const ShaderData *sd)
{
#ifdef __HAIR__
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ if(sd->type & PRIMITIVE_ALL_CURVE) {
return ATTR_PRIM_CURVE;
}
else
@@ -53,12 +53,12 @@ ccl_device_inline AttributeDescriptor attribute_not_found()
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
{
- if(ccl_fetch(sd, object) == PRIM_NONE) {
+ if(sd->object == PRIM_NONE) {
return attribute_not_found();
}
/* for SVM, find attribute by unique id */
- uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
+ uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
attr_offset += attribute_primitive_type(kg, sd);
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
@@ -73,7 +73,7 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const Sh
AttributeDescriptor desc;
desc.element = (AttributeElement)attr_map.y;
- if(ccl_fetch(sd, prim) == PRIM_NONE &&
+ if(sd->prim == PRIM_NONE &&
desc.element != ATTR_ELEMENT_MESH &&
desc.element != ATTR_ELEMENT_VOXEL &&
desc.element != ATTR_ELEMENT_OBJECT)
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 9de335403ce..bb33b91847e 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -22,6 +22,12 @@ CCL_NAMESPACE_BEGIN
#ifdef __HAIR__
+#if defined(__KERNEL_CUDA__) && (__CUDA_ARCH__ < 300)
+# define ccl_device_curveintersect ccl_device
+#else
+# define ccl_device_curveintersect ccl_device_forceinline
+#endif
+
/* Reading attributes on various curve elements */
ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
@@ -32,22 +38,22 @@ ccl_device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd,
if(dy) *dy = 0.0f;
#endif
- return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim));
+ return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
}
else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float f0 = kernel_tex_fetch(__attributes_float, desc.offset + k0);
float f1 = kernel_tex_fetch(__attributes_float, desc.offset + k1);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
+ if(dx) *dx = sd->du.dx*(f1 - f0);
if(dy) *dy = 0.0f;
#endif
- return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1;
+ return (1.0f - sd->u)*f0 + sd->u*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
@@ -71,22 +77,22 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim)));
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
}
else if(desc.element == ATTR_ELEMENT_CURVE_KEY || desc.element == ATTR_ELEMENT_CURVE_KEY_MOTION) {
- float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k0));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + k1));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*(f1 - f0);
+ if(dx) *dx = sd->du.dx*(f1 - f0);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
#endif
- return (1.0f - ccl_fetch(sd, u))*f0 + ccl_fetch(sd, u)*f1;
+ return (1.0f - sd->u)*f0 + sd->u*f1;
}
else {
#ifdef __RAY_DIFFERENTIALS__
@@ -104,22 +110,22 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
{
float r = 0.0f;
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
- float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
+ if(sd->type & PRIMITIVE_ALL_CURVE) {
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float4 P_curve[2];
- if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
+ if(sd->type & PRIMITIVE_CURVE) {
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
}
else {
- motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve);
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
}
- r = (P_curve[1].w - P_curve[0].w) * ccl_fetch(sd, u) + P_curve[0].w;
+ r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
}
return r*2.0f;
@@ -130,8 +136,8 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd)
{
- float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float4 P_curve[2];
@@ -139,7 +145,7 @@ ccl_device float3 curve_motion_center_location(KernelGlobals *kg, ShaderData *sd
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
- return float4_to_float3(P_curve[1]) * ccl_fetch(sd, u) + float4_to_float3(P_curve[0]) * (1.0f - ccl_fetch(sd, u));
+ return float4_to_float3(P_curve[1]) * sd->u + float4_to_float3(P_curve[0]) * (1.0f - sd->u);
}
/* Curve tangent normal */
@@ -148,14 +154,14 @@ ccl_device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
{
float3 tgN = make_float3(0.0f,0.0f,0.0f);
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ if(sd->type & PRIMITIVE_ALL_CURVE) {
- tgN = -(-ccl_fetch(sd, I) - ccl_fetch(sd, dPdu) * (dot(ccl_fetch(sd, dPdu),-ccl_fetch(sd, I)) / len_squared(ccl_fetch(sd, dPdu))));
+ tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) / len_squared(sd->dPdu)));
tgN = normalize(tgN);
/* need to find suitable scaled gd for corrected normal */
#if 0
- tgN = normalize(tgN - gd * ccl_fetch(sd, dPdu));
+ tgN = normalize(tgN - gd * sd->dPdu);
#endif
}
@@ -222,13 +228,22 @@ ccl_device_inline ssef transform_point_T3(const ssef t[3], const ssef &a)
#ifdef __KERNEL_SSE2__
/* Pass P and dir by reference to aligned vector */
-ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
+ccl_device_curveintersect bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
const float3 &P, const float3 &dir, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
#else
-ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
+ccl_device_curveintersect bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 dir, uint visibility, int object, int curveAddr, float time,int type, uint *lcg_state, float difl, float extmax)
#endif
{
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
float epsilon = 0.0f;
float r_st, r_en;
@@ -255,9 +270,9 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
int ka = max(k0 - 1, v00.x);
int kb = min(k1 + 1, v00.x + v00.y - 1);
-#ifdef __KERNEL_AVX2__
+#if defined(__KERNEL_AVX2__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
avxf P_curve_0_1, P_curve_2_3;
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve_0_1 = _mm256_loadu2_m128(&kg->__curve_keys.data[k0].x, &kg->__curve_keys.data[ka].x);
P_curve_2_3 = _mm256_loadu2_m128(&kg->__curve_keys.data[kb].x, &kg->__curve_keys.data[k1].x);
}
@@ -268,7 +283,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
#else /* __KERNEL_AVX2__ */
ssef P_curve[4];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = load4f(&kg->__curve_keys.data[ka].x);
P_curve[1] = load4f(&kg->__curve_keys.data[k0].x);
P_curve[2] = load4f(&kg->__curve_keys.data[k1].x);
@@ -290,7 +305,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
ssef htfm1 = shuffle<1, 0, 1, 3>(load1f_first(extract<0>(d_ss)), vdir0);
ssef htfm2 = shuffle<1, 3, 2, 3>(mul_shuf, vdir0);
-#ifdef __KERNEL_AVX2__
+#if defined(__KERNEL_AVX2__) && (!defined(_MSC_VER) || _MSC_VER > 1800)
const avxf vPP = _mm256_broadcast_ps(&P.m128);
const avxf htfm00 = avxf(htfm0.m128, htfm0.m128);
const avxf htfm11 = avxf(htfm1.m128, htfm1.m128);
@@ -363,7 +378,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
float4 P_curve[4];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
@@ -679,7 +694,7 @@ ccl_device_forceinline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Inte
return hit;
}
-ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
+ccl_device_curveintersect bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isect,
float3 P, float3 direction, uint visibility, int object, int curveAddr, float time, int type, uint *lcg_state, float difl, float extmax)
{
/* define few macros to minimize code duplication for SSE */
@@ -689,6 +704,15 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
# define dot3(x, y) dot(x, y)
#endif
+ const bool is_curve_primitive = (type & PRIMITIVE_CURVE);
+
+ if(!is_curve_primitive && kernel_data.bvh.use_bvh_steps) {
+ const float2 prim_time = kernel_tex_fetch(__prim_time, curveAddr);
+ if(time < prim_time.x || time > prim_time.y) {
+ return false;
+ }
+ }
+
int segment = PRIMITIVE_UNPACK_SEGMENT(type);
/* curve Intersection check */
int flags = kernel_data.curve.curveflags;
@@ -703,7 +727,7 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
#ifndef __KERNEL_SSE2__
float4 P_curve[2];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
}
@@ -738,7 +762,7 @@ ccl_device_forceinline bool bvh_curve_intersect(KernelGlobals *kg, Intersection
#else
ssef P_curve[2];
- if(type & PRIMITIVE_CURVE) {
+ if(is_curve_primitive) {
P_curve[0] = load4f(&kg->__curve_keys.data[k0].x);
P_curve[1] = load4f(&kg->__curve_keys.data[k1].x);
}
@@ -948,7 +972,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_itfm);
+ Transform tfm = sd->ob_itfm;
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
#endif
@@ -961,7 +985,7 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 v00 = kernel_tex_fetch(__curves, prim);
- int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(ccl_fetch(sd, type));
+ int k0 = __float_as_int(v00.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
float3 tg;
@@ -972,14 +996,14 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float4 P_curve[4];
- if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
+ if(sd->type & PRIMITIVE_CURVE) {
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
}
else {
- motion_cardinal_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), ka, k0, k1, kb, P_curve);
+ motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
}
float3 p[4];
@@ -991,43 +1015,43 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
P = P + D*t;
#ifdef __UV__
- ccl_fetch(sd, u) = isect->u;
- ccl_fetch(sd, v) = 0.0f;
+ sd->u = isect->u;
+ sd->v = 0.0f;
#endif
tg = normalize(curvetangent(isect->u, p[0], p[1], p[2], p[3]));
if(kernel_data.curve.curveflags & CURVE_KN_RIBBONS) {
- ccl_fetch(sd, Ng) = normalize(-(D - tg * (dot(tg, D))));
+ sd->Ng = normalize(-(D - tg * (dot(tg, D))));
}
else {
/* direction from inside to surface of curve */
float3 p_curr = curvepoint(isect->u, p[0], p[1], p[2], p[3]);
- ccl_fetch(sd, Ng) = normalize(P - p_curr);
+ sd->Ng = normalize(P - p_curr);
/* adjustment for changing radius */
float gd = isect->v;
if(gd != 0.0f) {
- ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg;
- ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
}
}
/* todo: sometimes the normal is still so that this is detected as
* backfacing even if cull backfaces is enabled */
- ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
+ sd->N = sd->Ng;
}
else {
float4 P_curve[2];
- if(ccl_fetch(sd, type) & PRIMITIVE_CURVE) {
+ if(sd->type & PRIMITIVE_CURVE) {
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
}
else {
- motion_curve_keys(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), k0, k1, P_curve);
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
}
float l = 1.0f;
@@ -1038,39 +1062,39 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float3 dif = P - float4_to_float3(P_curve[0]);
#ifdef __UV__
- ccl_fetch(sd, u) = dot(dif,tg)/l;
- ccl_fetch(sd, v) = 0.0f;
+ sd->u = dot(dif,tg)/l;
+ sd->v = 0.0f;
#endif
if(flag & CURVE_KN_TRUETANGENTGNORMAL) {
- ccl_fetch(sd, Ng) = -(D - tg * dot(tg, D));
- ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
+ sd->Ng = -(D - tg * dot(tg, D));
+ sd->Ng = normalize(sd->Ng);
}
else {
float gd = isect->v;
/* direction from inside to surface of curve */
- ccl_fetch(sd, Ng) = (dif - tg * ccl_fetch(sd, u) * l) / (P_curve[0].w + ccl_fetch(sd, u) * l * gd);
+ sd->Ng = (dif - tg * sd->u * l) / (P_curve[0].w + sd->u * l * gd);
/* adjustment for changing radius */
if(gd != 0.0f) {
- ccl_fetch(sd, Ng) = ccl_fetch(sd, Ng) - gd * tg;
- ccl_fetch(sd, Ng) = normalize(ccl_fetch(sd, Ng));
+ sd->Ng = sd->Ng - gd * tg;
+ sd->Ng = normalize(sd->Ng);
}
}
- ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
+ sd->N = sd->Ng;
}
#ifdef __DPDU__
/* dPdu/dPdv */
- ccl_fetch(sd, dPdu) = tg;
- ccl_fetch(sd, dPdv) = cross(tg, ccl_fetch(sd, Ng));
+ sd->dPdu = tg;
+ sd->dPdv = cross(tg, sd->Ng);
#endif
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_tfm);
+ Transform tfm = sd->ob_tfm;
#else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
#endif
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
index d57d74ea882..f74995becf5 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
@@ -48,7 +48,7 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
return P;
}
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_itfm);
+ Transform tfm = sd->ob_itfm;
# else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -77,7 +77,7 @@ ccl_device_inline float3 motion_triangle_refine(KernelGlobals *kg,
if(isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_tfm);
+ Transform tfm = sd->ob_tfm;
# else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -116,7 +116,7 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
# ifdef __INTERSECTION_REFINE__
if(isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_itfm);
+ Transform tfm = sd->ob_itfm;
# else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -144,7 +144,7 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
if(isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_tfm);
+ Transform tfm = sd->ob_tfm;
# else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -166,14 +166,15 @@ float3 motion_triangle_refine_subsurface(KernelGlobals *kg,
* time and do a ray intersection with the resulting triangle.
*/
-ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg,
- Intersection *isect,
- float3 P,
- float3 dir,
- float time,
- uint visibility,
- int object,
- int prim_addr)
+ccl_device_inline bool motion_triangle_intersect(
+ KernelGlobals *kg,
+ Intersection *isect,
+ float3 P,
+ float3 dir,
+ float time,
+ uint visibility,
+ int object,
+ int prim_addr)
{
/* Primitive index for vertex location lookup. */
int prim = kernel_tex_fetch(__prim_index, prim_addr);
@@ -185,11 +186,15 @@ ccl_device_inline bool motion_triangle_intersect(KernelGlobals *kg,
motion_triangle_vertices(kg, fobject, prim, time, verts);
/* Ray-triangle intersection, unoptimized. */
float t, u, v;
- if(ray_triangle_intersect_uv(P,
- dir,
- isect->t,
- verts[2], verts[0], verts[1],
- &u, &v, &t))
+ if(ray_triangle_intersect(P,
+ dir,
+ isect->t,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ (ssef*)verts,
+#else
+ verts[0], verts[1], verts[2],
+#endif
+ &u, &v, &t))
{
#ifdef __VISIBILITY_FLAG__
/* Visibility flag test. we do it here under the assumption
@@ -237,11 +242,15 @@ ccl_device_inline void motion_triangle_intersect_subsurface(
motion_triangle_vertices(kg, fobject, prim, time, verts);
/* Ray-triangle intersection, unoptimized. */
float t, u, v;
- if(ray_triangle_intersect_uv(P,
- dir,
- tmax,
- verts[2], verts[0], verts[1],
- &u, &v, &t))
+ if(ray_triangle_intersect(P,
+ dir,
+ tmax,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ (ssef*)verts,
+#else
+ verts[0], verts[1], verts[2],
+#endif
+ &u, &v, &t))
{
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_shader.h b/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
index 0e024a05db6..cb456056e20 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle_shader.h
@@ -39,26 +39,26 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
bool subsurface)
{
/* Get shader. */
- ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim));
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* Get motion info. */
/* TODO(sergey): This logic is really similar to motion_triangle_vertices(),
* can we de-duplicate something here?
*/
int numsteps, numverts;
- object_motion_info(kg, ccl_fetch(sd, object), &numsteps, &numverts, NULL);
+ object_motion_info(kg, sd->object, &numsteps, &numverts, NULL);
/* Figure out which steps we need to fetch and their interpolation factor. */
int maxstep = numsteps*2;
- int step = min((int)(ccl_fetch(sd, time)*maxstep), maxstep-1);
- float t = ccl_fetch(sd, time)*maxstep - step;
+ int step = min((int)(sd->time*maxstep), maxstep-1);
+ float t = sd->time*maxstep - step;
/* Find attribute. */
AttributeElement elem;
- int offset = find_attribute_motion(kg, ccl_fetch(sd, object),
+ int offset = find_attribute_motion(kg, sd->object,
ATTR_STD_MOTION_VERTEX_POSITION,
&elem);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
/* Fetch vertex coordinates. */
float3 verts[3], next_verts[3];
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step, verts);
motion_triangle_verts_for_step(kg, tri_vindex, offset, numverts, numsteps, step+1, next_verts);
/* Interpolate between steps. */
@@ -68,7 +68,7 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
/* Compute refined position. */
#ifdef __SUBSURFACE__
if(subsurface) {
- ccl_fetch(sd, P) = motion_triangle_refine_subsurface(kg,
+ sd->P = motion_triangle_refine_subsurface(kg,
sd,
isect,
ray,
@@ -77,29 +77,29 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
else
#endif /* __SUBSURFACE__*/
{
- ccl_fetch(sd, P) = motion_triangle_refine(kg, sd, isect, ray, verts);
+ sd->P = motion_triangle_refine(kg, sd, isect, ray, verts);
}
/* Compute face normal. */
float3 Ng;
- if(ccl_fetch(sd, object_flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ if(sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
Ng = normalize(cross(verts[2] - verts[0], verts[1] - verts[0]));
}
else {
Ng = normalize(cross(verts[1] - verts[0], verts[2] - verts[0]));
}
- ccl_fetch(sd, Ng) = Ng;
- ccl_fetch(sd, N) = Ng;
+ sd->Ng = Ng;
+ sd->N = Ng;
/* Compute derivatives of P w.r.t. uv. */
#ifdef __DPDU__
- ccl_fetch(sd, dPdu) = (verts[0] - verts[2]);
- ccl_fetch(sd, dPdv) = (verts[1] - verts[2]);
+ sd->dPdu = (verts[0] - verts[2]);
+ sd->dPdv = (verts[1] - verts[2]);
#endif
/* Compute smooth normal. */
- if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
+ if(sd->shader & SHADER_SMOOTH_NORMAL) {
/* Find attribute. */
AttributeElement elem;
int offset = find_attribute_motion(kg,
- ccl_fetch(sd, object),
+ sd->object,
ATTR_STD_MOTION_VERTEX_NORMAL,
&elem);
kernel_assert(offset != ATTR_STD_NOT_FOUND);
@@ -112,10 +112,10 @@ ccl_device_noinline void motion_triangle_shader_setup(KernelGlobals *kg,
normals[1] = (1.0f - t)*normals[1] + t*next_normals[1];
normals[2] = (1.0f - t)*normals[2] + t*next_normals[2];
/* Interpolate between vertices. */
- float u = ccl_fetch(sd, u);
- float v = ccl_fetch(sd, v);
+ float u = sd->u;
+ float v = sd->v;
float w = 1.0f - u - v;
- ccl_fetch(sd, N) = (u*normals[0] + v*normals[1] + w*normals[2]);
+ sd->N = (u*normals[0] + v*normals[1] + w*normals[2]);
}
}
diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h
index f51b2d18657..6ecdfe0173a 100644
--- a/intern/cycles/kernel/geom/geom_object.h
+++ b/intern/cycles/kernel/geom/geom_object.h
@@ -137,9 +137,9 @@ ccl_device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg
ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point_auto(&ccl_fetch(sd, ob_tfm), *P);
+ *P = transform_point_auto(&sd->ob_tfm, *P);
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
*P = transform_point(&tfm, *P);
#endif
}
@@ -149,9 +149,9 @@ ccl_device_inline void object_position_transform(KernelGlobals *kg, const Shader
ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
{
#ifdef __OBJECT_MOTION__
- *P = transform_point_auto(&ccl_fetch(sd, ob_itfm), *P);
+ *P = transform_point_auto(&sd->ob_itfm, *P);
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
*P = transform_point(&tfm, *P);
#endif
}
@@ -161,12 +161,12 @@ ccl_device_inline void object_inverse_position_transform(KernelGlobals *kg, cons
ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{
#ifdef __OBJECT_MOTION__
- if((ccl_fetch(sd, object) != OBJECT_NONE) || (ccl_fetch(sd, type) == PRIMITIVE_LAMP)) {
- *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_tfm), *N));
+ if((sd->object != OBJECT_NONE) || (sd->type == PRIMITIVE_LAMP)) {
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_tfm, *N));
}
#else
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
+ if(sd->object != OBJECT_NONE) {
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
}
#endif
@@ -177,9 +177,9 @@ ccl_device_inline void object_inverse_normal_transform(KernelGlobals *kg, const
ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderData *sd, float3 *N)
{
#ifdef __OBJECT_MOTION__
- *N = normalize(transform_direction_transposed_auto(&ccl_fetch(sd, ob_itfm), *N));
+ *N = normalize(transform_direction_transposed_auto(&sd->ob_itfm, *N));
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
*N = normalize(transform_direction_transposed(&tfm, *N));
#endif
}
@@ -189,9 +189,9 @@ ccl_device_inline void object_normal_transform(KernelGlobals *kg, const ShaderDa
ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction_auto(&ccl_fetch(sd, ob_tfm), *D);
+ *D = transform_direction_auto(&sd->ob_tfm, *D);
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
*D = transform_direction(&tfm, *D);
#endif
}
@@ -201,9 +201,9 @@ ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData
ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
{
#ifdef __OBJECT_MOTION__
- *D = transform_direction_auto(&ccl_fetch(sd, ob_itfm), *D);
+ *D = transform_direction_auto(&sd->ob_itfm, *D);
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
*D = transform_direction(&tfm, *D);
#endif
}
@@ -212,13 +212,13 @@ ccl_device_inline void object_inverse_dir_transform(KernelGlobals *kg, const Sha
ccl_device_inline float3 object_location(KernelGlobals *kg, const ShaderData *sd)
{
- if(ccl_fetch(sd, object) == OBJECT_NONE)
+ if(sd->object == OBJECT_NONE)
return make_float3(0.0f, 0.0f, 0.0f);
#ifdef __OBJECT_MOTION__
- return make_float3(ccl_fetch(sd, ob_tfm).x.w, ccl_fetch(sd, ob_tfm).y.w, ccl_fetch(sd, ob_tfm).z.w);
+ return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
#else
- Transform tfm = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
+ Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
#endif
}
@@ -326,7 +326,7 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
ccl_device int shader_pass_id(KernelGlobals *kg, const ShaderData *sd)
{
- return kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE + 1);
+ return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE + 1);
}
/* Particle data from which object was instanced */
@@ -425,7 +425,13 @@ ccl_device_inline float3 bvh_inverse_direction(float3 dir)
/* Transform ray into object space to enter static object in BVH */
-ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t)
+ccl_device_inline float bvh_instance_push(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float t)
{
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
@@ -435,8 +441,11 @@ ccl_device_inline void bvh_instance_push(KernelGlobals *kg, int object, const Ra
*dir = bvh_clamp_direction(normalize_len(transform_direction(&tfm, ray->D), &len));
*idir = bvh_inverse_direction(*dir);
- if(*t != FLT_MAX)
- *t *= len;
+ if(t != FLT_MAX) {
+ t *= len;
+ }
+
+ return t;
}
#ifdef __QBVH__
@@ -473,16 +482,24 @@ ccl_device_inline void qbvh_instance_push(KernelGlobals *kg,
/* Transorm ray to exit static object in BVH */
-ccl_device_inline void bvh_instance_pop(KernelGlobals *kg, int object, const Ray *ray, float3 *P, float3 *dir, float3 *idir, ccl_addr_space float *t)
+ccl_device_inline float bvh_instance_pop(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float t)
{
- if(*t != FLT_MAX) {
+ if(t != FLT_MAX) {
Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
- *t /= len(transform_direction(&tfm, ray->D));
+ t /= len(transform_direction(&tfm, ray->D));
}
*P = ray->P;
*dir = bvh_clamp_direction(ray->D);
*idir = bvh_inverse_direction(*dir);
+
+ return t;
}
/* Same as above, but returns scale factor to apply to multiple intersection distances */
@@ -501,13 +518,13 @@ ccl_device_inline void bvh_instance_pop_factor(KernelGlobals *kg, int object, co
#ifdef __OBJECT_MOTION__
/* Transform ray into object space to enter motion blurred object in BVH */
-ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg,
+ccl_device_inline float bvh_instance_motion_push(KernelGlobals *kg,
int object,
const Ray *ray,
float3 *P,
float3 *dir,
float3 *idir,
- ccl_addr_space float *t,
+ float t,
Transform *itfm)
{
object_fetch_transform_motion_test(kg, object, ray->time, itfm);
@@ -518,8 +535,11 @@ ccl_device_inline void bvh_instance_motion_push(KernelGlobals *kg,
*dir = bvh_clamp_direction(normalize_len(transform_direction(itfm, ray->D), &len));
*idir = bvh_inverse_direction(*dir);
- if(*t != FLT_MAX)
- *t *= len;
+ if(t != FLT_MAX) {
+ t *= len;
+ }
+
+ return t;
}
#ifdef __QBVH__
@@ -557,22 +577,24 @@ ccl_device_inline void qbvh_instance_motion_push(KernelGlobals *kg,
/* Transorm ray to exit motion blurred object in BVH */
-ccl_device_inline void bvh_instance_motion_pop(KernelGlobals *kg,
- int object,
- const Ray *ray,
- float3 *P,
- float3 *dir,
- float3 *idir,
- ccl_addr_space float *t,
- Transform *itfm)
-{
- if(*t != FLT_MAX) {
- *t /= len(transform_direction(itfm, ray->D));
+ccl_device_inline float bvh_instance_motion_pop(KernelGlobals *kg,
+ int object,
+ const Ray *ray,
+ float3 *P,
+ float3 *dir,
+ float3 *idir,
+ float t,
+ Transform *itfm)
+{
+ if(t != FLT_MAX) {
+ t /= len(transform_direction(itfm, ray->D));
}
*P = ray->P;
*dir = bvh_clamp_direction(ray->D);
*idir = bvh_inverse_direction(*dir);
+
+ return t;
}
/* Same as above, but returns scale factor to apply to multiple intersection distances */
diff --git a/intern/cycles/kernel/geom/geom_patch.h b/intern/cycles/kernel/geom/geom_patch.h
index 6a0ff5a4a04..5663b598508 100644
--- a/intern/cycles/kernel/geom/geom_patch.h
+++ b/intern/cycles/kernel/geom/geom_patch.h
@@ -267,7 +267,7 @@ ccl_device float patch_eval_float(KernelGlobals *kg, const ShaderData *sd, int o
float weights_du[PATCH_MAX_CONTROL_VERTS];
float weights_dv[PATCH_MAX_CONTROL_VERTS];
- int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel,
+ int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
indices, weights, weights_du, weights_dv);
float val = 0.0f;
@@ -294,7 +294,7 @@ ccl_device float3 patch_eval_float3(KernelGlobals *kg, const ShaderData *sd, int
float weights_du[PATCH_MAX_CONTROL_VERTS];
float weights_dv[PATCH_MAX_CONTROL_VERTS];
- int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel,
+ int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
indices, weights, weights_du, weights_dv);
float3 val = make_float3(0.0f, 0.0f, 0.0f);
@@ -321,7 +321,7 @@ ccl_device float3 patch_eval_uchar4(KernelGlobals *kg, const ShaderData *sd, int
float weights_du[PATCH_MAX_CONTROL_VERTS];
float weights_dv[PATCH_MAX_CONTROL_VERTS];
- int num_control = patch_eval_control_verts(kg, ccl_fetch(sd, object), patch, u, v, channel,
+ int num_control = patch_eval_control_verts(kg, sd->object, patch, u, v, channel,
indices, weights, weights_du, weights_dv);
float3 val = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/geom/geom_primitive.h b/intern/cycles/kernel/geom/geom_primitive.h
index 8a73bb2f78b..90a9c2147cc 100644
--- a/intern/cycles/kernel/geom/geom_primitive.h
+++ b/intern/cycles/kernel/geom/geom_primitive.h
@@ -28,19 +28,19 @@ ccl_device_inline float primitive_attribute_float(KernelGlobals *kg,
const AttributeDescriptor desc,
float *dx, float *dy)
{
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
+ if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
if(subd_triangle_patch(kg, sd) == ~0)
return triangle_attribute_float(kg, sd, desc, dx, dy);
else
return subd_triangle_attribute_float(kg, sd, desc, dx, dy);
}
#ifdef __HAIR__
- else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ else if(sd->type & PRIMITIVE_ALL_CURVE) {
return curve_attribute_float(kg, sd, desc, dx, dy);
}
#endif
#ifdef __VOLUME__
- else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float(kg, sd, desc, dx, dy);
}
#endif
@@ -56,19 +56,19 @@ ccl_device_inline float3 primitive_attribute_float3(KernelGlobals *kg,
const AttributeDescriptor desc,
float3 *dx, float3 *dy)
{
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE) {
+ if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
if(subd_triangle_patch(kg, sd) == ~0)
return triangle_attribute_float3(kg, sd, desc, dx, dy);
else
return subd_triangle_attribute_float3(kg, sd, desc, dx, dy);
}
#ifdef __HAIR__
- else if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ else if(sd->type & PRIMITIVE_ALL_CURVE) {
return curve_attribute_float3(kg, sd, desc, dx, dy);
}
#endif
#ifdef __VOLUME__
- else if(ccl_fetch(sd, object) != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
+ else if(sd->object != OBJECT_NONE && desc.element == ATTR_ELEMENT_VOXEL) {
return volume_attribute_float3(kg, sd, desc, dx, dy);
}
#endif
@@ -118,9 +118,9 @@ ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, in
ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __HAIR__
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)
+ if(sd->type & PRIMITIVE_ALL_CURVE)
# ifdef __DPDU__
- return normalize(ccl_fetch(sd, dPdu));
+ return normalize(sd->dPdu);
# else
return make_float3(0.0f, 0.0f, 0.0f);
# endif
@@ -133,12 +133,12 @@ ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
float3 data = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
object_normal_transform(kg, sd, &data);
- return cross(ccl_fetch(sd, N), normalize(cross(data, ccl_fetch(sd, N))));
+ return cross(sd->N, normalize(cross(data, sd->N)));
}
else {
/* otherwise use surface derivatives */
#ifdef __DPDU__
- return normalize(ccl_fetch(sd, dPdu));
+ return normalize(sd->dPdu);
#else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
@@ -153,17 +153,17 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
float3 center;
#ifdef __HAIR__
- bool is_curve_primitive = ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE;
+ bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
if(is_curve_primitive) {
center = curve_motion_center_location(kg, sd);
- if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
+ if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &center);
}
}
else
#endif
- center = ccl_fetch(sd, P);
+ center = sd->P;
float3 motion_pre = center, motion_post = center;
@@ -173,16 +173,16 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
if(desc.offset != ATTR_STD_NOT_FOUND) {
/* get motion info */
int numverts, numkeys;
- object_motion_info(kg, ccl_fetch(sd, object), NULL, &numverts, &numkeys);
+ object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
/* lookup attributes */
motion_pre = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
- desc.offset += (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys;
+ desc.offset += (sd->type & PRIMITIVE_ALL_TRIANGLE)? numverts: numkeys;
motion_post = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
#ifdef __HAIR__
- if(is_curve_primitive && (ccl_fetch(sd, object_flag) & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
+ if(is_curve_primitive && (sd->object_flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
object_position_transform(kg, sd, &motion_pre);
object_position_transform(kg, sd, &motion_post);
}
@@ -193,10 +193,10 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
* transformation was set match the world/object space of motion_pre/post */
Transform tfm;
- tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_PRE);
+ tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
motion_pre = transform_point(&tfm, motion_pre);
- tfm = object_fetch_vector_transform(kg, ccl_fetch(sd, object), OBJECT_VECTOR_MOTION_POST);
+ tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
motion_post = transform_point(&tfm, motion_post);
float3 motion_center;
diff --git a/intern/cycles/kernel/geom/geom_subd_triangle.h b/intern/cycles/kernel/geom/geom_subd_triangle.h
index 647840dc696..044e82f03d4 100644
--- a/intern/cycles/kernel/geom/geom_subd_triangle.h
+++ b/intern/cycles/kernel/geom/geom_subd_triangle.h
@@ -22,14 +22,14 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline uint subd_triangle_patch(KernelGlobals *kg, const ShaderData *sd)
{
- return (ccl_fetch(sd, prim) != PRIM_NONE) ? kernel_tex_fetch(__tri_patch, ccl_fetch(sd, prim)) : ~0;
+ return (sd->prim != PRIM_NONE) ? kernel_tex_fetch(__tri_patch, sd->prim) : ~0;
}
/* UV coords of triangle within patch */
ccl_device_inline void subd_triangle_patch_uv(KernelGlobals *kg, const ShaderData *sd, float2 uv[3])
{
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
uv[0] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.x);
uv[1] = kernel_tex_fetch(__tri_patch_uv, tri_vindex.y);
@@ -110,7 +110,7 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
float2 dpdv = uv[1] - uv[2];
/* p is [s, t] */
- float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + uv[2];
+ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
float a, dads, dadt;
a = patch_eval_float(kg, sd, desc.offset, patch, p.x, p.y, 0, &dads, &dadt);
@@ -123,8 +123,8 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
float dtdv = dpdv.y;
if(dx) {
- float dudx = ccl_fetch(sd, du).dx;
- float dvdx = ccl_fetch(sd, dv).dx;
+ float dudx = sd->du.dx;
+ float dvdx = sd->dv.dx;
float dsdx = dsdu*dudx + dsdv*dvdx;
float dtdx = dtdu*dudx + dtdv*dvdx;
@@ -132,8 +132,8 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
*dx = dads*dsdx + dadt*dtdx;
}
if(dy) {
- float dudy = ccl_fetch(sd, du).dy;
- float dvdy = ccl_fetch(sd, dv).dy;
+ float dudy = sd->du.dy;
+ float dvdy = sd->dv.dy;
float dsdy = dsdu*dudy + dsdv*dvdy;
float dtdy = dtdu*dudy + dtdv*dvdy;
@@ -174,11 +174,11 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
- if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+ if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+ if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
#endif
- return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
}
else if(desc.element == ATTR_ELEMENT_CORNER) {
float2 uv[3];
@@ -202,11 +202,11 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals *kg, const
float c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
- if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+ if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+ if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
#endif
- return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
}
else {
if(dx) *dx = 0.0f;
@@ -229,7 +229,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, con
float2 dpdv = uv[1] - uv[2];
/* p is [s, t] */
- float2 p = dpdu * ccl_fetch(sd, u) + dpdv * ccl_fetch(sd, v) + uv[2];
+ float2 p = dpdu * sd->u + dpdv * sd->v + uv[2];
float3 a, dads, dadt;
@@ -248,8 +248,8 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, con
float dtdv = dpdv.y;
if(dx) {
- float dudx = ccl_fetch(sd, du).dx;
- float dvdx = ccl_fetch(sd, dv).dx;
+ float dudx = sd->du.dx;
+ float dvdx = sd->dv.dx;
float dsdx = dsdu*dudx + dsdv*dvdx;
float dtdx = dtdu*dudx + dtdv*dvdx;
@@ -257,8 +257,8 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, con
*dx = dads*dsdx + dadt*dtdx;
}
if(dy) {
- float dudy = ccl_fetch(sd, du).dy;
- float dvdy = ccl_fetch(sd, dv).dy;
+ float dudy = sd->du.dy;
+ float dvdy = sd->dv.dy;
float dsdy = dsdu*dudy + dsdv*dvdy;
float dtdy = dtdu*dudy + dtdv*dvdy;
@@ -299,11 +299,11 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, con
float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
- if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+ if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+ if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
#endif
- return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
}
else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
float2 uv[3];
@@ -337,11 +337,11 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals *kg, con
float3 c = mix(mix(f0, f1, uv[2].x), mix(f3, f2, uv[2].x), uv[2].y);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*a + ccl_fetch(sd, dv).dx*b - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*c;
- if(dy) *dy = ccl_fetch(sd, du).dy*a + ccl_fetch(sd, dv).dy*b - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*c;
+ if(dx) *dx = sd->du.dx*a + sd->dv.dx*b - (sd->du.dx + sd->dv.dx)*c;
+ if(dy) *dy = sd->du.dy*a + sd->dv.dy*b - (sd->du.dy + sd->dv.dy)*c;
#endif
- return ccl_fetch(sd, u)*a + ccl_fetch(sd, v)*b + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*c;
+ return sd->u*a + sd->v*b + (1.0f - sd->u - sd->v)*c;
}
else {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/geom/geom_triangle.h b/intern/cycles/kernel/geom/geom_triangle.h
index 3229091bbb0..47778553b94 100644
--- a/intern/cycles/kernel/geom/geom_triangle.h
+++ b/intern/cycles/kernel/geom/geom_triangle.h
@@ -26,13 +26,13 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
{
/* load triangle vertices */
- const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
const float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+0));
const float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+1));
const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w+2));
/* return normal */
- if(ccl_fetch(sd, object_flag) & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
+ if(sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
return normalize(cross(v2 - v0, v1 - v0));
}
else {
@@ -110,34 +110,34 @@ ccl_device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *s
if(dx) *dx = 0.0f;
if(dy) *dy = 0.0f;
- return kernel_tex_fetch(__attributes_float, desc.offset + ccl_fetch(sd, prim));
+ return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
}
else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
- if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
+ if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+ if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
- return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
+ return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else if(desc.element == ATTR_ELEMENT_CORNER) {
- int tri = desc.offset + ccl_fetch(sd, prim)*3;
+ int tri = desc.offset + sd->prim*3;
float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
- if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
+ if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+ if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
- return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
+ return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
if(dx) *dx = 0.0f;
@@ -153,24 +153,24 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
- return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + ccl_fetch(sd, prim)));
+ return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
}
else if(desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
- uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, ccl_fetch(sd, prim));
+ uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
- if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
+ if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+ if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
- return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
+ return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else if(desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
- int tri = desc.offset + ccl_fetch(sd, prim)*3;
+ int tri = desc.offset + sd->prim*3;
float3 f0, f1, f2;
if(desc.element == ATTR_ELEMENT_CORNER) {
@@ -185,11 +185,11 @@ ccl_device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData
}
#ifdef __RAY_DIFFERENTIALS__
- if(dx) *dx = ccl_fetch(sd, du).dx*f0 + ccl_fetch(sd, dv).dx*f1 - (ccl_fetch(sd, du).dx + ccl_fetch(sd, dv).dx)*f2;
- if(dy) *dy = ccl_fetch(sd, du).dy*f0 + ccl_fetch(sd, dv).dy*f1 - (ccl_fetch(sd, du).dy + ccl_fetch(sd, dv).dy)*f2;
+ if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
+ if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
#endif
- return ccl_fetch(sd, u)*f0 + ccl_fetch(sd, v)*f1 + (1.0f - ccl_fetch(sd, u) - ccl_fetch(sd, v))*f2;
+ return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
}
else {
if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index 4db121d94f4..804e74d7e37 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -22,232 +22,50 @@
CCL_NAMESPACE_BEGIN
-/* Workaround stupidness of CUDA/OpenCL which doesn't allow to access indexed
- * component of float3 value.
- */
-#ifndef __KERNEL_CPU__
-# define IDX(vec, idx) \
- ((idx == 0) ? ((vec).x) : ( (idx == 1) ? ((vec).y) : ((vec).z) ))
-#else
-# define IDX(vec, idx) ((vec)[idx])
-#endif
-
-/* Ray-Triangle intersection for BVH traversal
- *
- * Sven Woop
- * Watertight Ray/Triangle Intersection
- *
- * http://jcgt.org/published/0002/01/05/paper.pdf
- */
-
-/* Precalculated data for the ray->tri intersection. */
-typedef struct IsectPrecalc {
- /* Maximal dimension kz, and orthogonal dimensions. */
- int kx, ky, kz;
-
- /* Shear constants. */
- float Sx, Sy, Sz;
-} IsectPrecalc;
-
-#if (defined(__KERNEL_OPENCL_APPLE__)) || \
- (defined(__KERNEL_CUDA__) && (defined(i386) || defined(_M_IX86)))
-ccl_device_noinline
-#else
-ccl_device_inline
-#endif
-void triangle_intersect_precalc(float3 dir,
- IsectPrecalc *isect_precalc)
-{
- /* Calculate dimension where the ray direction is maximal. */
-#ifndef __KERNEL_SSE__
- int kz = util_max_axis(make_float3(fabsf(dir.x),
- fabsf(dir.y),
- fabsf(dir.z)));
- int kx = kz + 1; if(kx == 3) kx = 0;
- int ky = kx + 1; if(ky == 3) ky = 0;
-#else
- int kx, ky, kz;
- /* Avoiding mispredicted branch on direction. */
- kz = util_max_axis(fabs(dir));
- static const char inc_xaxis[] = {1, 2, 0, 55};
- static const char inc_yaxis[] = {2, 0, 1, 55};
- kx = inc_xaxis[kz];
- ky = inc_yaxis[kz];
-#endif
-
- float dir_kz = IDX(dir, kz);
-
- /* Swap kx and ky dimensions to preserve winding direction of triangles. */
- if(dir_kz < 0.0f) {
- int tmp = kx;
- kx = ky;
- ky = tmp;
- }
-
- /* Calculate the shear constants. */
- float inv_dir_z = 1.0f / dir_kz;
- isect_precalc->Sx = IDX(dir, kx) * inv_dir_z;
- isect_precalc->Sy = IDX(dir, ky) * inv_dir_z;
- isect_precalc->Sz = inv_dir_z;
-
- /* Store the dimensions. */
- isect_precalc->kx = kx;
- isect_precalc->ky = ky;
- isect_precalc->kz = kz;
-}
-
-/* TODO(sergey): Make it general utility function. */
-ccl_device_inline float xor_signmask(float x, int y)
-{
- return __int_as_float(__float_as_int(x) ^ y);
-}
-
ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
- const IsectPrecalc *isect_precalc,
Intersection *isect,
float3 P,
+ float3 dir,
uint visibility,
int object,
int prim_addr)
{
- const int kx = isect_precalc->kx;
- const int ky = isect_precalc->ky;
- const int kz = isect_precalc->kz;
- const float Sx = isect_precalc->Sx;
- const float Sy = isect_precalc->Sy;
- const float Sz = isect_precalc->Sz;
-
- /* Calculate vertices relative to ray origin. */
const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__)
- const avxf avxf_P(P.m128, P.m128);
-
- const avxf tri_ab = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 0);
- const avxf tri_bc = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 1);
-
- const avxf AB = tri_ab - avxf_P;
- const avxf BC = tri_bc - avxf_P;
-
- const __m256i permute_mask = _mm256_set_epi32(0x3, kz, ky, kx, 0x3, kz, ky, kx);
-
- const avxf AB_k = shuffle(AB, permute_mask);
- const avxf BC_k = shuffle(BC, permute_mask);
-
- /* Akz, Akz, Bkz, Bkz, Bkz, Bkz, Ckz, Ckz */
- const avxf ABBC_kz = shuffle<2>(AB_k, BC_k);
-
- /* Akx, Aky, Bkx, Bky, Bkx,Bky, Ckx, Cky */
- const avxf ABBC_kxy = shuffle<0,1,0,1>(AB_k, BC_k);
-
- const avxf Sxy(Sy, Sx, Sy, Sx);
-
- /* Ax, Ay, Bx, By, Bx, By, Cx, Cy */
- const avxf ABBC_xy = nmadd(ABBC_kz, Sxy, ABBC_kxy);
-
- float ABBC_kz_array[8];
- _mm256_storeu_ps((float*)&ABBC_kz_array, ABBC_kz);
-
- const float A_kz = ABBC_kz_array[0];
- const float B_kz = ABBC_kz_array[2];
- const float C_kz = ABBC_kz_array[6];
-
- /* By, Bx, Cy, Cx, By, Bx, Ay, Ax */
- const avxf BCBA_yx = permute<3,2,7,6,3,2,1,0>(ABBC_xy);
-
- const avxf neg_mask(0,0,0,0,0x80000000, 0x80000000, 0x80000000, 0x80000000);
-
- /* W U V
- * (AxBy-AyBx) (BxCy-ByCx) XX XX (BxBy-ByBx) (CxAy-CyAx) XX XX
- */
- const avxf WUxxxxVxx_neg = _mm256_hsub_ps(ABBC_xy * BCBA_yx, neg_mask /* Dont care */);
-
- const avxf WUVWnegWUVW = permute<0,1,5,0,0,1,5,0>(WUxxxxVxx_neg) ^ neg_mask;
-
- /* Calculate scaled barycentric coordinates. */
- float WUVW_array[4];
- _mm_storeu_ps((float*)&WUVW_array, _mm256_castps256_ps128 (WUVWnegWUVW));
-
- const float W = WUVW_array[0];
- const float U = WUVW_array[1];
- const float V = WUVW_array[2];
-
- const int WUVW_mask = 0x7 & _mm256_movemask_ps(WUVWnegWUVW);
- const int WUVW_zero = 0x7 & _mm256_movemask_ps(_mm256_cmp_ps(WUVWnegWUVW,
- _mm256_setzero_ps(), 0));
-
- if(!((WUVW_mask == 7) || (WUVW_mask == 0)) && ((WUVW_mask | WUVW_zero) != 7)) {
- return false;
- }
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
#else
const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0),
tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1),
tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2);
- const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
- const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
- const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
-
- const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
- const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
- const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
-
- /* Perform shear and scale of vertices. */
- const float Ax = A_kx - Sx * A_kz;
- const float Ay = A_ky - Sy * A_kz;
- const float Bx = B_kx - Sx * B_kz;
- const float By = B_ky - Sy * B_kz;
- const float Cx = C_kx - Sx * C_kz;
- const float Cy = C_ky - Sy * C_kz;
-
- /* Calculate scaled barycentric coordinates. */
- float U = Cx * By - Cy * Bx;
- float V = Ax * Cy - Ay * Cx;
- float W = Bx * Ay - By * Ax;
- if((U < 0.0f || V < 0.0f || W < 0.0f) &&
- (U > 0.0f || V > 0.0f || W > 0.0f))
- {
- return false;
- }
#endif
-
- /* Calculate determinant. */
- float det = U + V + W;
- if(UNLIKELY(det == 0.0f)) {
- return false;
- }
-
- /* Calculate scaled z-coordinates of vertices and use them to calculate
- * the hit distance.
- */
- const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz;
- const int sign_det = (__float_as_int(det) & 0x80000000);
- const float sign_T = xor_signmask(T, sign_det);
- if((sign_T < 0.0f) ||
- (sign_T > isect->t * xor_signmask(det, sign_det)))
+ float t, u, v;
+ if(ray_triangle_intersect(P,
+ dir,
+ isect->t,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ ssef_verts,
+#else
+ float4_to_float3(tri_a),
+ float4_to_float3(tri_b),
+ float4_to_float3(tri_c),
+#endif
+ &u, &v, &t))
{
- return false;
- }
-
#ifdef __VISIBILITY_FLAG__
- /* visibility flag test. we do it here under the assumption
- * that most triangles are culled by node flags */
- if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
+ /* Visibility flag test. we do it here under the assumption
+ * that most triangles are culled by node flags.
+ */
+ if(kernel_tex_fetch(__prim_visibility, prim_addr) & visibility)
#endif
- {
-#ifdef __KERNEL_CUDA__
- if(A == B && B == C) {
- return false;
+ {
+ isect->prim = prim_addr;
+ isect->object = object;
+ isect->type = PRIMITIVE_TRIANGLE;
+ isect->u = u;
+ isect->v = v;
+ isect->t = t;
+ return true;
}
-#endif
- /* Normalize U, V, W, and T. */
- const float inv_det = 1.0f / det;
- isect->prim = prim_addr;
- isect->object = object;
- isect->type = PRIMITIVE_TRIANGLE;
- isect->u = U * inv_det;
- isect->v = V * inv_det;
- isect->t = T * inv_det;
- return true;
}
return false;
}
@@ -260,138 +78,37 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
#ifdef __SUBSURFACE__
ccl_device_inline void triangle_intersect_subsurface(
KernelGlobals *kg,
- const IsectPrecalc *isect_precalc,
SubsurfaceIntersection *ss_isect,
float3 P,
+ float3 dir,
int object,
int prim_addr,
float tmax,
uint *lcg_state,
int max_hits)
{
- const int kx = isect_precalc->kx;
- const int ky = isect_precalc->ky;
- const int kz = isect_precalc->kz;
- const float Sx = isect_precalc->Sx;
- const float Sy = isect_precalc->Sy;
- const float Sz = isect_precalc->Sz;
-
- /* Calculate vertices relative to ray origin. */
const uint tri_vindex = kernel_tex_fetch(__prim_tri_index, prim_addr);
- const float4 tri_a = kernel_tex_fetch(__prim_tri_verts, tri_vindex+0),
- tri_b = kernel_tex_fetch(__prim_tri_verts, tri_vindex+1),
- tri_c = kernel_tex_fetch(__prim_tri_verts, tri_vindex+2);
-
-#if defined(__KERNEL_AVX2__) && defined(__KERNEL_SSE__)
- const avxf avxf_P(P.m128, P.m128);
-
- const avxf tri_ab = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 0);
- const avxf tri_bc = kernel_tex_fetch_avxf(__prim_tri_verts, tri_vindex + 1);
-
- const avxf AB = tri_ab - avxf_P;
- const avxf BC = tri_bc - avxf_P;
-
- const __m256i permuteMask = _mm256_set_epi32(0x3, kz, ky, kx, 0x3, kz, ky, kx);
-
- const avxf AB_k = shuffle(AB, permuteMask);
- const avxf BC_k = shuffle(BC, permuteMask);
-
- /* Akz, Akz, Bkz, Bkz, Bkz, Bkz, Ckz, Ckz */
- const avxf ABBC_kz = shuffle<2>(AB_k, BC_k);
-
- /* Akx, Aky, Bkx, Bky, Bkx,Bky, Ckx, Cky */
- const avxf ABBC_kxy = shuffle<0,1,0,1>(AB_k, BC_k);
-
- const avxf Sxy(Sy, Sx, Sy, Sx);
-
- /* Ax, Ay, Bx, By, Bx, By, Cx, Cy */
- const avxf ABBC_xy = nmadd(ABBC_kz, Sxy, ABBC_kxy);
-
- float ABBC_kz_array[8];
- _mm256_storeu_ps((float*)&ABBC_kz_array, ABBC_kz);
-
- const float A_kz = ABBC_kz_array[0];
- const float B_kz = ABBC_kz_array[2];
- const float C_kz = ABBC_kz_array[6];
-
- /* By, Bx, Cy, Cx, By, Bx, Ay, Ax */
- const avxf BCBA_yx = permute<3,2,7,6,3,2,1,0>(ABBC_xy);
-
- const avxf negMask(0,0,0,0,0x80000000, 0x80000000, 0x80000000, 0x80000000);
-
- /* W U V
- * (AxBy-AyBx) (BxCy-ByCx) XX XX (BxBy-ByBx) (CxAy-CyAx) XX XX
- */
- const avxf WUxxxxVxx_neg = _mm256_hsub_ps(ABBC_xy * BCBA_yx, negMask /* Dont care */);
-
- const avxf WUVWnegWUVW = permute<0,1,5,0,0,1,5,0>(WUxxxxVxx_neg) ^ negMask;
-
- /* Calculate scaled barycentric coordinates. */
- float WUVW_array[4];
- _mm_storeu_ps((float*)&WUVW_array, _mm256_castps256_ps128 (WUVWnegWUVW));
-
- const float W = WUVW_array[0];
- const float U = WUVW_array[1];
- const float V = WUVW_array[2];
-
- const int WUVW_mask = 0x7 & _mm256_movemask_ps(WUVWnegWUVW);
- const int WUVW_zero = 0x7 & _mm256_movemask_ps(_mm256_cmp_ps(WUVWnegWUVW,
- _mm256_setzero_ps(), 0));
-
- if(!((WUVW_mask == 7) || (WUVW_mask == 0)) && ((WUVW_mask | WUVW_zero) != 7)) {
- return;
- }
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const ssef *ssef_verts = (ssef*)&kg->__prim_tri_verts.data[tri_vindex];
#else
- const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
- const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
- const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
-
- const float A_kx = IDX(A, kx), A_ky = IDX(A, ky), A_kz = IDX(A, kz);
- const float B_kx = IDX(B, kx), B_ky = IDX(B, ky), B_kz = IDX(B, kz);
- const float C_kx = IDX(C, kx), C_ky = IDX(C, ky), C_kz = IDX(C, kz);
-
- /* Perform shear and scale of vertices. */
- const float Ax = A_kx - Sx * A_kz;
- const float Ay = A_ky - Sy * A_kz;
- const float Bx = B_kx - Sx * B_kz;
- const float By = B_ky - Sy * B_kz;
- const float Cx = C_kx - Sx * C_kz;
- const float Cy = C_ky - Sy * C_kz;
-
- /* Calculate scaled barycentric coordinates. */
- float U = Cx * By - Cy * Bx;
- float V = Ax * Cy - Ay * Cx;
- float W = Bx * Ay - By * Ax;
-
- if((U < 0.0f || V < 0.0f || W < 0.0f) &&
- (U > 0.0f || V > 0.0f || W > 0.0f))
- {
- return;
- }
+ const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)),
+ tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
+ tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
#endif
-
- /* Calculate determinant. */
- float det = U + V + W;
- if(UNLIKELY(det == 0.0f)) {
- return;
- }
-
- /* Calculate scaled z−coordinates of vertices and use them to calculate
- * the hit distance.
- */
- const int sign_det = (__float_as_int(det) & 0x80000000);
- const float T = (U * A_kz + V * B_kz + W * C_kz) * Sz;
- const float sign_T = xor_signmask(T, sign_det);
- if((sign_T < 0.0f) ||
- (sign_T > tmax * xor_signmask(det, sign_det)))
+ float t, u, v;
+ if(!ray_triangle_intersect(P,
+ dir,
+ tmax,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ ssef_verts,
+#else
+ tri_a, tri_b, tri_c,
+#endif
+ &u, &v, &t))
{
return;
}
- /* Normalize U, V, W, and T. */
- const float inv_det = 1.0f / det;
-
- const float t = T * inv_det;
for(int i = min(max_hits, ss_isect->num_hits) - 1; i >= 0; --i) {
if(ss_isect->hits[i].t == t) {
return;
@@ -418,18 +135,19 @@ ccl_device_inline void triangle_intersect_subsurface(
isect->prim = prim_addr;
isect->object = object;
isect->type = PRIMITIVE_TRIANGLE;
- isect->u = U * inv_det;
- isect->v = V * inv_det;
+ isect->u = u;
+ isect->v = v;
isect->t = t;
/* Record geometric normal. */
- /* TODO(sergey): Use float4_to_float3() on just an edges. */
- const float3 v0 = float4_to_float3(tri_a);
- const float3 v1 = float4_to_float3(tri_b);
- const float3 v2 = float4_to_float3(tri_c);
- ss_isect->Ng[hit] = normalize(cross(v1 - v0, v2 - v0));
-}
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const float3 tri_a = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+0)),
+ tri_b = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+1)),
+ tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
#endif
+ ss_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
+}
+#endif /* __SUBSURFACE__ */
/* Refine triangle intersection to more precise hit point. For rays that travel
* far the precision is often not so good, this reintersects the primitive from
@@ -457,7 +175,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
return P;
}
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_itfm);
+ Transform tfm = sd->ob_itfm;
# else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_INVERSE_TRANSFORM);
# endif
@@ -491,7 +209,7 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
if(isect->object != OBJECT_NONE) {
# ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_tfm);
+ Transform tfm = sd->ob_tfm;
# else
Transform tfm = object_fetch_transform(kg, isect->object, OBJECT_TRANSFORM);
# endif
@@ -519,7 +237,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_itfm);
+ Transform tfm = sd->ob_itfm;
#else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -557,7 +275,7 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
if(isect->object != OBJECT_NONE) {
#ifdef __OBJECT_MOTION__
- Transform tfm = ccl_fetch(sd, ob_tfm);
+ Transform tfm = sd->ob_tfm;
#else
Transform tfm = object_fetch_transform(kg,
isect->object,
@@ -570,6 +288,4 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
return P;
}
-#undef IDX
-
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/geom/geom_volume.h b/intern/cycles/kernel/geom/geom_volume.h
index 03724c955be..1e0ef5201c9 100644
--- a/intern/cycles/kernel/geom/geom_volume.h
+++ b/intern/cycles/kernel/geom/geom_volume.h
@@ -64,7 +64,7 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals *kg,
ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
{
- float3 P = volume_normalized_position(kg, sd, ccl_fetch(sd, P));
+ float3 P = volume_normalized_position(kg, sd, sd->P);
#ifdef __KERNEL_CUDA__
# if __CUDA_ARCH__ >= 300
CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset);
@@ -91,7 +91,7 @@ ccl_device float volume_attribute_float(KernelGlobals *kg, const ShaderData *sd,
ccl_device float3 volume_attribute_float3(KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float3 *dx, float3 *dy)
{
- float3 P = volume_normalized_position(kg, sd, ccl_fetch(sd, P));
+ float3 P = volume_normalized_position(kg, sd, sd->P);
#ifdef __KERNEL_CUDA__
# if __CUDA_ARCH__ >= 300
CUtexObject tex = kernel_tex_fetch(__bindless_mapping, desc.offset);
diff --git a/intern/cycles/kernel/kernel.h b/intern/cycles/kernel/kernel.h
index 9279a94c13a..06c0fb2fbca 100644
--- a/intern/cycles/kernel/kernel.h
+++ b/intern/cycles/kernel/kernel.h
@@ -19,7 +19,8 @@
/* CPU Kernel Interface */
-#include "util_types.h"
+#include "util/util_types.h"
+#include "kernel/kernel_types.h"
CCL_NAMESPACE_BEGIN
@@ -28,6 +29,7 @@ CCL_NAMESPACE_BEGIN
#define KERNEL_FUNCTION_FULL_NAME(name) KERNEL_NAME_EVAL(KERNEL_ARCH, name)
struct KernelGlobals;
+struct KernelData;
KernelGlobals *kernel_globals_create();
void kernel_globals_free(KernelGlobals *kg);
@@ -46,31 +48,31 @@ void kernel_tex_copy(KernelGlobals *kg,
ExtensionType extension = EXTENSION_REPEAT);
#define KERNEL_ARCH cpu
-#include "kernels/cpu/kernel_cpu.h"
+#include "kernel/kernels/cpu/kernel_cpu.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
# define KERNEL_ARCH cpu_sse2
-# include "kernels/cpu/kernel_cpu.h"
+# include "kernel/kernels/cpu/kernel_cpu.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
# define KERNEL_ARCH cpu_sse3
-# include "kernels/cpu/kernel_cpu.h"
+# include "kernel/kernels/cpu/kernel_cpu.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
# define KERNEL_ARCH cpu_sse41
-# include "kernels/cpu/kernel_cpu.h"
+# include "kernel/kernels/cpu/kernel_cpu.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
# define KERNEL_ARCH cpu_avx
-# include "kernels/cpu/kernel_cpu.h"
+# include "kernel/kernels/cpu/kernel_cpu.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
# define KERNEL_ARCH cpu_avx2
-# include "kernels/cpu/kernel_cpu.h"
+# include "kernel/kernels/cpu/kernel_cpu.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index 6c3ee6b8098..823d30dde78 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -52,10 +52,17 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
{
eval->diffuse = value;
}
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis = make_float3(0.0f, 0.0f, 0.0f);
+#endif
}
-ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
+ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value, float mis_weight)
{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis += value;
+#endif
+ value *= mis_weight;
#ifdef __PASSES__
if(eval->use_light_pass) {
if(CLOSURE_IS_BSDF_DIFFUSE(type))
@@ -96,7 +103,7 @@ ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
}
}
-ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
+ccl_device_inline void bsdf_eval_mis(BsdfEval *eval, float value)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
@@ -115,8 +122,19 @@ ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
}
}
+ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float value)
+{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis *= value;
+#endif
+ bsdf_eval_mis(eval, value);
+}
+
ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
{
+#ifdef __SHADOW_TRICKS__
+ eval->sum_no_mis *= value;
+#endif
#ifdef __PASSES__
if(eval->use_light_pass) {
eval->diffuse *= value;
@@ -134,7 +152,7 @@ ccl_device_inline void bsdf_eval_mul3(BsdfEval *eval, float3 value)
#endif
}
-ccl_device_inline float3 bsdf_eval_sum(BsdfEval *eval)
+ccl_device_inline float3 bsdf_eval_sum(const BsdfEval *eval)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
@@ -198,6 +216,12 @@ ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
{
L->emission = make_float3(0.0f, 0.0f, 0.0f);
}
+
+#ifdef __SHADOW_TRICKS__
+ L->path_total = make_float3(0.0f, 0.0f, 0.0f);
+ L->path_total_shaded = make_float3(0.0f, 0.0f, 0.0f);
+ L->shadow_color = make_float3(0.0f, 0.0f, 0.0f);
+#endif
}
ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, ccl_addr_space float3 *throughput,
@@ -252,7 +276,12 @@ ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 thro
}
}
-ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce)
+ccl_device_inline void path_radiance_accum_ao(PathRadiance *L,
+ float3 throughput,
+ float3 alpha,
+ float3 bsdf,
+ float3 ao,
+ int bounce)
{
#ifdef __PASSES__
if(L->use_light_pass) {
@@ -271,6 +300,26 @@ ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput
{
L->emission += throughput*bsdf*ao;
}
+
+#ifdef __SHADOW_TRICKS__
+ float3 light = throughput * bsdf;
+ L->path_total += light;
+ L->path_total_shaded += ao * light;
+#endif
+}
+
+ccl_device_inline void path_radiance_accum_total_ao(
+ PathRadiance *L,
+ float3 throughput,
+ float3 bsdf)
+{
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * bsdf;
+#else
+ (void) L;
+ (void) throughput;
+ (void) bsdf;
+#endif
}
ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
@@ -301,15 +350,38 @@ ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 through
{
L->emission += throughput*bsdf_eval->diffuse*shadow;
}
+
+#ifdef __SHADOW_TRICKS__
+ float3 light = throughput * bsdf_eval->sum_no_mis;
+ L->path_total += light;
+ L->path_total_shaded += shadow * light;
+#endif
+}
+
+ccl_device_inline void path_radiance_accum_total_light(
+ PathRadiance *L,
+ float3 throughput,
+ const BsdfEval *bsdf_eval)
+{
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * bsdf_eval->sum_no_mis;
+#else
+ (void) L;
+ (void) throughput;
+ (void) bsdf_eval;
+#endif
}
-ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
+ccl_device_inline void path_radiance_accum_background(PathRadiance *L,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float3 value)
{
#ifdef __PASSES__
if(L->use_light_pass) {
- if(bounce == 0)
+ if(state->bounce == 0)
L->background += throughput*value;
- else if(bounce == 1)
+ else if(state->bounce == 1)
L->direct_emission += throughput*value;
else
L->indirect += throughput*value;
@@ -319,6 +391,13 @@ ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 th
{
L->emission += throughput*value;
}
+
+#ifdef __SHADOW_TRICKS__
+ L->path_total += throughput * value;
+ if(state->flag & PATH_RAY_SHADOW_CATCHER_ONLY) {
+ L->path_total_shaded += throughput * value;
+ }
+#endif
}
ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
@@ -399,7 +478,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
/* Reject invalid value */
- if(!isfinite(sum)) {
+ if(!isfinite_safe(sum)) {
kernel_assert(!"Non-finite sum in path_radiance_clamp_and_sum!");
L_sum = make_float3(0.0f, 0.0f, 0.0f);
@@ -468,7 +547,7 @@ ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadi
/* Reject invalid value */
float sum = fabsf((L_sum).x) + fabsf((L_sum).y) + fabsf((L_sum).z);
- if(!isfinite(sum)) {
+ if(!isfinite_safe(sum)) {
kernel_assert(!"Non-finite final sum in path_radiance_clamp_and_sum!");
L_sum = make_float3(0.0f, 0.0f, 0.0f);
}
@@ -501,5 +580,34 @@ ccl_device_inline void path_radiance_accum_sample(PathRadiance *L, PathRadiance
L->emission += L_sample->emission * fac;
}
-CCL_NAMESPACE_END
+#ifdef __SHADOW_TRICKS__
+/* Calculate current shadow of the path. */
+ccl_device_inline float path_radiance_sum_shadow(const PathRadiance *L)
+{
+ float path_total = average(L->path_total);
+ float path_total_shaded = average(L->path_total_shaded);
+ if(path_total != 0.0f) {
+ return path_total_shaded / path_total;
+ }
+ return 1.0f;
+}
+/* Calculate final light sum and transparency for shadow catcher object. */
+ccl_device_inline float3 path_radiance_sum_shadowcatcher(KernelGlobals *kg,
+ const PathRadiance *L,
+ ccl_addr_space float* L_transparent)
+{
+ const float shadow = path_radiance_sum_shadow(L);
+ float3 L_sum;
+ if(kernel_data.background.transparent) {
+ *L_transparent = shadow;
+ L_sum = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ else {
+ L_sum = L->shadow_color * shadow;
+ }
+ return L_sum;
+}
+#endif
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 5bcc57cdcdf..f18d145f7cf 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -54,7 +54,8 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF);
shader_eval_surface(kg, sd, &rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
- /* TODO, disable the closures we won't need */
+ /* TODO, disable more closures we don't need besides transparent */
+ shader_bsdf_disable_transparency(kg, sd);
#ifdef __BRANCHED_PATH__
if(!kernel_data.integrator.branched) {
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index dedac6b1465..0df5217d97a 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -457,7 +457,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
{
if(kernel_data.cam.type != CAMERA_PANORAMA) {
/* perspective / ortho */
- if(ccl_fetch(sd, object) == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
+ if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
P += camera_position(kg);
Transform tfm = kernel_data.cam.worldtondc;
@@ -467,7 +467,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
/* panorama */
Transform tfm = kernel_data.cam.worldtocamera;
- if(ccl_fetch(sd, object) != OBJECT_NONE)
+ if(sd->object != OBJECT_NONE)
P = normalize(transform_point(&tfm, P));
else
P = normalize(transform_direction(&tfm, P));
diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index 9d1f3bdc918..ae7c9b836c4 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -35,15 +35,24 @@
# define __NODES_FEATURES__ NODE_FEATURE_ALL
#endif
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_simd.h"
-#include "util_half.h"
-#include "util_types.h"
-#include "util_texture.h"
+#include "util/util_debug.h"
+#include "util/util_math.h"
+#include "util/util_simd.h"
+#include "util/util_half.h"
+#include "util/util_types.h"
+#include "util/util_texture.h"
#define ccl_addr_space
+#define ccl_local_id(d) 0
+#define ccl_global_id(d) (kg->global_id[d])
+
+#define ccl_local_size(d) 1
+#define ccl_global_size(d) (kg->global_size[d])
+
+#define ccl_group_id(d) ccl_global_id(d)
+#define ccl_num_groups(d) ccl_global_size(d)
+
/* On x86_64, versions of glibc < 2.16 have an issue where expf is
* much slower than the double version. This was fixed in glibc 2.16.
*/
@@ -78,9 +87,9 @@ template<typename T> struct texture {
ccl_always_inline avxf fetch_avxf(const int index)
{
kernel_assert(index >= 0 && (index+1) < width);
- ssef *ssefData = (ssef*)data;
- ssef *ssefNodeData = &ssefData[index];
- return _mm256_loadu_ps((float *)ssefNodeData);
+ ssef *ssef_data = (ssef*)data;
+ ssef *ssef_node_data = &ssef_data[index];
+ return _mm256_loadu_ps((float *)ssef_node_data);
}
#endif
diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h
index e0c7b17c6a0..39e98c7dda6 100644
--- a/intern/cycles/kernel/kernel_compat_cuda.h
+++ b/intern/cycles/kernel/kernel_compat_cuda.h
@@ -38,7 +38,7 @@
#define ccl_device __device__ __inline__
# define ccl_device_forceinline __device__ __forceinline__
-#if (__KERNEL_CUDA_VERSION__ == 80) && (__CUDA_ARCH__ < 500)
+#if __CUDA_ARCH__ < 500
# define ccl_device_inline __device__ __forceinline__
#else
# define ccl_device_inline __device__ __inline__
@@ -46,6 +46,9 @@
#define ccl_device_noinline __device__ __noinline__
#define ccl_global
#define ccl_constant
+#define ccl_local __shared__
+#define ccl_local_param
+#define ccl_private
#define ccl_may_alias
#define ccl_addr_space
#define ccl_restrict __restrict__
@@ -57,8 +60,54 @@
/* Types */
-#include "util_half.h"
-#include "util_types.h"
+#include "util/util_half.h"
+#include "util/util_types.h"
+
+/* Work item functions */
+
+ccl_device_inline uint ccl_local_id(uint d)
+{
+ switch(d) {
+ case 0: return threadIdx.x;
+ case 1: return threadIdx.y;
+ case 2: return threadIdx.z;
+ default: return 0;
+ }
+}
+
+#define ccl_global_id(d) (ccl_group_id(d) * ccl_local_size(d) + ccl_local_id(d))
+
+ccl_device_inline uint ccl_local_size(uint d)
+{
+ switch(d) {
+ case 0: return blockDim.x;
+ case 1: return blockDim.y;
+ case 2: return blockDim.z;
+ default: return 0;
+ }
+}
+
+#define ccl_global_size(d) (ccl_num_groups(d) * ccl_local_size(d))
+
+ccl_device_inline uint ccl_group_id(uint d)
+{
+ switch(d) {
+ case 0: return blockIdx.x;
+ case 1: return blockIdx.y;
+ case 2: return blockIdx.z;
+ default: return 0;
+ }
+}
+
+ccl_device_inline uint ccl_num_groups(uint d)
+{
+ switch(d) {
+ case 0: return gridDim.x;
+ case 1: return gridDim.y;
+ case 2: return gridDim.z;
+ default: return 0;
+ }
+}
/* Textures */
diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h
index f076e3a7d37..c2263ac0d49 100644
--- a/intern/cycles/kernel/kernel_compat_opencl.h
+++ b/intern/cycles/kernel/kernel_compat_opencl.h
@@ -39,6 +39,7 @@
#define ccl_constant __constant
#define ccl_global __global
#define ccl_local __local
+#define ccl_local_param __local
#define ccl_private __private
#define ccl_restrict restrict
#define ccl_align(n) __attribute__((aligned(n)))
@@ -49,6 +50,15 @@
# define ccl_addr_space
#endif
+#define ccl_local_id(d) get_local_id(d)
+#define ccl_global_id(d) get_global_id(d)
+
+#define ccl_local_size(d) get_local_size(d)
+#define ccl_global_size(d) get_global_size(d)
+
+#define ccl_group_id(d) get_group_id(d)
+#define ccl_num_groups(d) get_num_groups(d)
+
/* Selective nodes compilation. */
#ifndef __NODES_MAX_GROUP__
# define __NODES_MAX_GROUP__ NODE_GROUP_LEVEL_MAX
@@ -133,8 +143,8 @@
/* define NULL */
#define NULL 0
-#include "util_half.h"
-#include "util_types.h"
+#include "util/util_half.h"
+#include "util/util_types.h"
#endif /* __KERNEL_COMPAT_OPENCL_H__ */
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 8c7c651a053..9e7d51f23f5 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -67,7 +67,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
ls->shader, ls->object, ls->prim,
ls->u, ls->v, t, time, false, ls->lamp);
- ls->Ng = ccl_fetch(emission_sd, Ng);
+ ls->Ng = emission_sd->Ng;
/* no path flag, we're evaluating this for all closures. that's weak but
* we'd have to do multiple evaluations otherwise */
@@ -76,7 +76,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
path_state_modify_bounce(state, false);
/* evaluate emissive closure */
- if(ccl_fetch(emission_sd, flag) & SD_EMISSION)
+ if(emission_sd->flag & SD_EMISSION)
eval = shader_emissive_eval(kg, emission_sd);
else
eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -112,7 +112,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
-ls->D,
dD,
ls->t,
- ccl_fetch(sd, time));
+ sd->time);
if(is_zero(light_eval))
return false;
@@ -120,7 +120,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
/* evaluate BSDF at shading point */
#ifdef __VOLUME__
- if(ccl_fetch(sd, prim) != PRIM_NONE)
+ if(sd->prim != PRIM_NONE)
shader_bsdf_eval(kg, sd, ls->D, eval, ls->pdf, ls->shader & SHADER_USE_MIS);
else {
float bsdf_pdf;
@@ -156,8 +156,13 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
if(bsdf_eval_is_zero(eval))
return false;
- if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
- float probability = max3(bsdf_eval_sum(eval)) * kernel_data.integrator.light_inv_rr_threshold;
+ if(kernel_data.integrator.light_inv_rr_threshold > 0.0f
+#ifdef __SHADOW_TRICKS__
+ && (state->flag & PATH_RAY_SHADOW_CATCHER) == 0
+#endif
+ )
+ {
+ float probability = max3(fabs(bsdf_eval_sum(eval))) * kernel_data.integrator.light_inv_rr_threshold;
if(probability < 1.0f) {
if(rand_terminate >= probability) {
return false;
@@ -168,8 +173,8 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
if(ls->shader & SHADER_CAST_SHADOW) {
/* setup ray */
- bool transmit = (dot(ccl_fetch(sd, Ng), ls->D) < 0.0f);
- ray->P = ray_offset(ccl_fetch(sd, P), (transmit)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
+ bool transmit = (dot(sd->Ng, ls->D) < 0.0f);
+ ray->P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
if(ls->t == FLT_MAX) {
/* distant light */
@@ -182,7 +187,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
ray->D = normalize_len(ray->D, &ray->t);
}
- ray->dP = ccl_fetch(sd, dP);
+ ray->dP = sd->dP;
ray->dD = differential3_zero();
}
else {
@@ -204,14 +209,14 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
float3 L = shader_emissive_eval(kg, sd);
#ifdef __HAIR__
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS) && (ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE))
+ if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE))
#else
- if(!(path_flag & PATH_RAY_MIS_SKIP) && (ccl_fetch(sd, flag) & SD_USE_MIS))
+ if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS))
#endif
{
/* multiple importance sampling, get triangle light pdf,
* and compute weight with respect to BSDF pdf */
- float pdf = triangle_light_pdf(kg, ccl_fetch(sd, Ng), ccl_fetch(sd, I), t);
+ float pdf = triangle_light_pdf(kg, sd->Ng, sd->I, t);
float mis_weight = power_heuristic(bsdf_pdf, pdf);
return L*mis_weight;
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index 8e66a3a0340..c9c97ea977e 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -16,6 +16,9 @@
/* Constant Globals */
+#ifndef __KERNEL_GLOBALS_H__
+#define __KERNEL_GLOBALS_H__
+
CCL_NAMESPACE_BEGIN
/* On the CPU, we pass along the struct KernelGlobals to nearly everywhere in
@@ -44,7 +47,7 @@ typedef struct KernelGlobals {
# define KERNEL_TEX(type, ttype, name) ttype name;
# define KERNEL_IMAGE_TEX(type, ttype, name)
-# include "kernel_textures.h"
+# include "kernel/kernel_textures.h"
KernelData __data;
@@ -64,6 +67,13 @@ typedef struct KernelGlobals {
/* Storage for decoupled volume steps. */
VolumeStep *decoupled_volume_steps[2];
int decoupled_volume_steps_index;
+
+ /* split kernel */
+ SplitData split_data;
+ SplitParams split_param_data;
+
+ int2 global_size;
+ int2 global_id;
} KernelGlobals;
#endif /* __KERNEL_CPU__ */
@@ -76,7 +86,10 @@ typedef struct KernelGlobals {
#ifdef __KERNEL_CUDA__
__constant__ KernelData __data;
-typedef struct KernelGlobals {} KernelGlobals;
+typedef struct KernelGlobals {
+ /* NOTE: Keep the size in sync with SHADOW_STACK_MAX_HITS. */
+ Intersection hits_stack[64];
+} KernelGlobals;
# ifdef __KERNEL_CUDA_TEX_STORAGE__
# define KERNEL_TEX(type, ttype, name) ttype name;
@@ -84,7 +97,7 @@ typedef struct KernelGlobals {} KernelGlobals;
# define KERNEL_TEX(type, ttype, name) const __constant__ __device__ type *name;
# endif
# define KERNEL_IMAGE_TEX(type, ttype, name) ttype name;
-# include "kernel_textures.h"
+# include "kernel/kernel_textures.h"
#endif /* __KERNEL_CUDA__ */
@@ -97,11 +110,11 @@ typedef ccl_addr_space struct KernelGlobals {
# define KERNEL_TEX(type, ttype, name) \
ccl_global type *name;
-# include "kernel_textures.h"
+# include "kernel/kernel_textures.h"
# ifdef __SPLIT_KERNEL__
- ShaderData *sd_input;
- Intersection *isect_shadow;
+ SplitData split_data;
+ SplitParams split_param_data;
# endif
} KernelGlobals;
@@ -143,3 +156,4 @@ ccl_device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int o
CCL_NAMESPACE_END
+#endif /* __KERNEL_GLOBALS_H__ */
diff --git a/intern/cycles/kernel/kernel_math.h b/intern/cycles/kernel/kernel_math.h
index 9bee5603474..bd0e23b7705 100644
--- a/intern/cycles/kernel/kernel_math.h
+++ b/intern/cycles/kernel/kernel_math.h
@@ -17,11 +17,11 @@
#ifndef __KERNEL_MATH_H__
#define __KERNEL_MATH_H__
-#include "util_color.h"
-#include "util_math.h"
-#include "util_math_fast.h"
-#include "util_texture.h"
-#include "util_transform.h"
+#include "util/util_color.h"
+#include "util/util_math.h"
+#include "util/util_math_fast.h"
+#include "util/util_math_intersect.h"
+#include "util/util_texture.h"
+#include "util/util_transform.h"
#endif /* __KERNEL_MATH_H__ */
-
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 7aec47e4957..ed523696571 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -19,16 +19,16 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void kernel_write_pass_float(ccl_global float *buffer, int sample, float value)
{
ccl_global float *buf = buffer;
-#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+#if defined(__SPLIT_KERNEL__)
atomic_add_and_fetch_float(buf, value);
#else
*buf = (sample == 0)? value: *buf + value;
-#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
+#endif /* __SPLIT_KERNEL__ */
}
ccl_device_inline void kernel_write_pass_float3(ccl_global float *buffer, int sample, float3 value)
{
-#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+#if defined(__SPLIT_KERNEL__)
ccl_global float *buf_x = buffer + 0;
ccl_global float *buf_y = buffer + 1;
ccl_global float *buf_z = buffer + 2;
@@ -39,12 +39,12 @@ ccl_device_inline void kernel_write_pass_float3(ccl_global float *buffer, int sa
#else
ccl_global float3 *buf = (ccl_global float3*)buffer;
*buf = (sample == 0)? value: *buf + value;
-#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
+#endif /* __SPLIT_KERNEL__ */
}
ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, int sample, float4 value)
{
-#if defined(__SPLIT_KERNEL__) && defined(__WORK_STEALING__)
+#if defined(__SPLIT_KERNEL__)
ccl_global float *buf_x = buffer + 0;
ccl_global float *buf_y = buffer + 1;
ccl_global float *buf_z = buffer + 2;
@@ -57,7 +57,7 @@ ccl_device_inline void kernel_write_pass_float4(ccl_global float *buffer, int sa
#else
ccl_global float4 *buf = (ccl_global float4*)buffer;
*buf = (sample == 0)? value: *buf + value;
-#endif // __SPLIT_KERNEL__ && __WORK_STEALING__
+#endif /* __SPLIT_KERNEL__ */
}
ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global float *buffer, PathRadiance *L,
@@ -75,18 +75,18 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
return;
if(!(path_flag & PATH_RAY_SINGLE_PASS_DONE)) {
- if(!(ccl_fetch(sd, flag) & SD_TRANSPARENT) ||
+ if(!(sd->flag & SD_TRANSPARENT) ||
kernel_data.film.pass_alpha_threshold == 0.0f ||
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold)
{
if(sample == 0) {
if(flag & PASS_DEPTH) {
- float depth = camera_distance(kg, ccl_fetch(sd, P));
+ float depth = camera_distance(kg, sd->P);
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth);
}
if(flag & PASS_OBJECT_ID) {
- float id = object_pass_id(kg, ccl_fetch(sd, object));
+ float id = object_pass_id(kg, sd->object);
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id);
}
if(flag & PASS_MATERIAL_ID) {
@@ -96,7 +96,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
}
if(flag & PASS_NORMAL) {
- float3 normal = ccl_fetch(sd, N);
+ float3 normal = sd->N;
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
@@ -127,7 +127,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg, ccl_global fl
float mist_start = kernel_data.film.mist_start;
float mist_inv_depth = kernel_data.film.mist_inv_depth;
- float depth = camera_distance(kg, ccl_fetch(sd, P));
+ float depth = camera_distance(kg, sd->P);
float mist = saturate((depth - mist_start)*mist_inv_depth);
/* falloff */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index f90701a8260..e7957042182 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -15,40 +15,41 @@
*/
#ifdef __OSL__
-# include "osl_shader.h"
+# include "kernel/osl/osl_shader.h"
#endif
-#include "kernel_random.h"
-#include "kernel_projection.h"
-#include "kernel_montecarlo.h"
-#include "kernel_differential.h"
-#include "kernel_camera.h"
+#include "kernel/kernel_random.h"
+#include "kernel/kernel_projection.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/kernel_differential.h"
+#include "kernel/kernel_camera.h"
-#include "geom/geom.h"
-#include "bvh/bvh.h"
+#include "kernel/geom/geom.h"
+#include "kernel/bvh/bvh.h"
-#include "kernel_accumulate.h"
-#include "kernel_shader.h"
-#include "kernel_light.h"
-#include "kernel_passes.h"
+#include "kernel/kernel_accumulate.h"
+#include "kernel/kernel_shader.h"
+#include "kernel/kernel_light.h"
+#include "kernel/kernel_passes.h"
#ifdef __SUBSURFACE__
-# include "kernel_subsurface.h"
+# include "kernel/kernel_subsurface.h"
#endif
#ifdef __VOLUME__
-# include "kernel_volume.h"
+# include "kernel/kernel_volume.h"
#endif
-#include "kernel_path_state.h"
-#include "kernel_shadow.h"
-#include "kernel_emission.h"
-#include "kernel_path_common.h"
-#include "kernel_path_surface.h"
-#include "kernel_path_volume.h"
+#include "kernel/kernel_path_state.h"
+#include "kernel/kernel_shadow.h"
+#include "kernel/kernel_emission.h"
+#include "kernel/kernel_path_common.h"
+#include "kernel/kernel_path_surface.h"
+#include "kernel/kernel_path_volume.h"
+#include "kernel/kernel_path_subsurface.h"
#ifdef __KERNEL_DEBUG__
-# include "kernel_debug.h"
+# include "kernel/kernel_debug.h"
#endif
CCL_NAMESPACE_BEGIN
@@ -75,22 +76,25 @@ ccl_device_noinline void kernel_path_ao(KernelGlobals *kg,
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
- if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
Ray light_ray;
float3 ao_shadow;
- light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
+ light_ray.P = ray_offset(sd->P, sd->Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
#ifdef __OBJECT_MOTION__
- light_ray.time = ccl_fetch(sd, time);
+ light_ray.time = sd->time;
#endif /* __OBJECT_MOTION__ */
- light_ray.dP = ccl_fetch(sd, dP);
+ light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, throughput, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
}
+ else {
+ path_radiance_accum_total_ao(L, throughput, ao_bsdf);
+ }
}
}
@@ -289,9 +293,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* sample background shader */
float3 L_background = indirect_background(kg, emission_sd, state, ray);
path_radiance_accum_background(L,
+ state,
throughput,
- L_background,
- state->bounce);
+ L_background);
#endif /* __BACKGROUND__ */
break;
@@ -311,6 +315,12 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
shader_merge_closures(sd);
#endif /* __BRANCHED_PATH__ */
+#ifdef __SHADOW_TRICKS__
+ if(!(sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
if(kernel_data.integrator.filter_glossy != FLT_MAX) {
@@ -373,7 +383,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
path_state_rng_2D(kg,
@@ -395,7 +405,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#if defined(__EMISSION__) && defined(__BRANCHED_PATH__)
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_indirect;
+ int all = (kernel_data.integrator.sample_all_lights_indirect) ||
+ (state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg,
rng,
sd,
@@ -413,172 +424,6 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
}
}
-#ifdef __SUBSURFACE__
-# ifndef __KERNEL_CUDA__
-ccl_device
-# else
-ccl_device_inline
-# endif
-bool kernel_path_subsurface_scatter(
- KernelGlobals *kg,
- ShaderData *sd,
- ShaderData *emission_sd,
- PathRadiance *L,
- PathState *state,
- RNG *rng,
- Ray *ray,
- float3 *throughput,
- SubsurfaceIndirectRays *ss_indirect)
-{
- float bssrdf_probability;
- ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
-
- /* modify throughput for picking bssrdf or bsdf */
- *throughput *= bssrdf_probability;
-
- /* do bssrdf scatter step if we picked a bssrdf closure */
- if(sc) {
- /* We should never have two consecutive BSSRDF bounces,
- * the second one should be converted to a diffuse BSDF to
- * avoid this.
- */
- kernel_assert(!ss_indirect->tracing);
-
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
-
- SubsurfaceIntersection ss_isect;
- float bssrdf_u, bssrdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
- int num_hits = subsurface_scatter_multi_intersect(kg,
- &ss_isect,
- sd,
- sc,
- &lcg_state,
- bssrdf_u, bssrdf_v,
- false);
-# ifdef __VOLUME__
- ss_indirect->need_update_volume_stack =
- kernel_data.integrator.use_volumes &&
- ccl_fetch(sd, object_flag) & SD_OBJECT_INTERSECTS_VOLUME;
-# endif /* __VOLUME__ */
-
- /* compute lighting with the BSDF closure */
- for(int hit = 0; hit < num_hits; hit++) {
- /* NOTE: We reuse the existing ShaderData, we assume the path
- * integration loop stops when this function returns true.
- */
- subsurface_scatter_multi_setup(kg,
- &ss_isect,
- hit,
- sd,
- state,
- state->flag,
- sc,
- false);
-
- PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
- Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
- float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
- PathRadiance *hit_L = &ss_indirect->L[ss_indirect->num_rays];
-
- *hit_state = *state;
- *hit_ray = *ray;
- *hit_tp = *throughput;
-
- hit_state->rng_offset += PRNG_BOUNCE_NUM;
-
- path_radiance_init(hit_L, kernel_data.film.use_light_pass);
- hit_L->direct_throughput = L->direct_throughput;
- path_radiance_copy_indirect(hit_L, L);
-
- kernel_path_surface_connect_light(kg, rng, sd, emission_sd, *hit_tp, state, hit_L);
-
- if(kernel_path_surface_bounce(kg,
- rng,
- sd,
- hit_tp,
- hit_state,
- hit_L,
- hit_ray))
- {
-# ifdef __LAMP_MIS__
- hit_state->ray_t = 0.0f;
-# endif /* __LAMP_MIS__ */
-
-# ifdef __VOLUME__
- if(ss_indirect->need_update_volume_stack) {
- Ray volume_ray = *ray;
- /* Setup ray from previous surface point to the new one. */
- volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
- &volume_ray.t);
-
- kernel_volume_stack_update_for_subsurface(
- kg,
- emission_sd,
- &volume_ray,
- hit_state->volume_stack);
- }
-# endif /* __VOLUME__ */
- path_radiance_reset_indirect(L);
- ss_indirect->num_rays++;
- }
- else {
- path_radiance_accum_sample(L, hit_L, 1);
- }
- }
- return true;
- }
- return false;
-}
-
-ccl_device_inline void kernel_path_subsurface_init_indirect(
- SubsurfaceIndirectRays *ss_indirect)
-{
- ss_indirect->tracing = false;
- ss_indirect->num_rays = 0;
-}
-
-ccl_device void kernel_path_subsurface_accum_indirect(
- SubsurfaceIndirectRays *ss_indirect,
- PathRadiance *L)
-{
- if(ss_indirect->tracing) {
- path_radiance_sum_indirect(L);
- path_radiance_accum_sample(&ss_indirect->direct_L, L, 1);
- if(ss_indirect->num_rays == 0) {
- *L = ss_indirect->direct_L;
- }
- }
-}
-
-ccl_device void kernel_path_subsurface_setup_indirect(
- KernelGlobals *kg,
- SubsurfaceIndirectRays *ss_indirect,
- PathState *state,
- Ray *ray,
- PathRadiance *L,
- float3 *throughput)
-{
- if(!ss_indirect->tracing) {
- ss_indirect->direct_L = *L;
- }
- ss_indirect->tracing = true;
-
- /* Setup state, ray and throughput for indirect SSS rays. */
- ss_indirect->num_rays--;
-
- Ray *indirect_ray = &ss_indirect->rays[ss_indirect->num_rays];
- PathRadiance *indirect_L = &ss_indirect->L[ss_indirect->num_rays];
-
- *state = ss_indirect->state[ss_indirect->num_rays];
- *ray = *indirect_ray;
- *L = *indirect_L;
- *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
-
- state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
-}
-
-#endif /* __SUBSURFACE__ */
ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
RNG *rng,
@@ -631,7 +476,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
}
if(state.bounce > kernel_data.integrator.ao_bounces) {
@@ -776,7 +621,7 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &emission_sd, &state, &ray);
- path_radiance_accum_background(&L, throughput, L_background, state.bounce);
+ path_radiance_accum_background(&L, &state, throughput, L_background);
#endif /* __BACKGROUND__ */
break;
@@ -790,6 +635,21 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
float rbsdf = path_state_rng_1D_for_decision(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rng, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
+#ifdef __SHADOW_TRICKS__
+ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if(state.flag & PATH_RAY_CAMERA) {
+ state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state.catcher_object = sd.object;
+ if(!kernel_data.background.transparent) {
+ L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
+ }
+ }
+ }
+ else {
+ state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* holdout */
#ifdef __HOLDOUT__
if(((sd.flag & SD_HOLDOUT) ||
@@ -907,7 +767,16 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
}
#endif /* __SUBSURFACE__ */
- float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, &L);
+ }
kernel_write_light_passes(kg, buffer, &L, sample);
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index ff2b828795d..36fd6c95fe7 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -42,21 +42,25 @@ ccl_device_inline void kernel_branched_path_ao(KernelGlobals *kg,
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
- if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
Ray light_ray;
float3 ao_shadow;
- light_ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
+ light_ray.P = ray_offset(sd->P, sd->Ng);
light_ray.D = ao_D;
light_ray.t = kernel_data.background.ao_distance;
#ifdef __OBJECT_MOTION__
- light_ray.time = ccl_fetch(sd, time);
+ light_ray.time = sd->time;
#endif /* __OBJECT_MOTION__ */
- light_ray.dP = ccl_fetch(sd, dP);
+ light_ray.dP = sd->dP;
light_ray.dD = differential3_zero();
- if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow))
+ if(!shadow_blocked(kg, emission_sd, state, &light_ray, &ao_shadow)) {
path_radiance_accum_ao(L, throughput*num_samples_inv, ao_alpha, ao_bsdf, ao_shadow, state->bounce);
+ }
+ else {
+ path_radiance_accum_total_ao(L, throughput*num_samples_inv, ao_bsdf);
+ }
}
}
}
@@ -67,8 +71,8 @@ ccl_device_noinline void kernel_branched_path_surface_indirect_light(KernelGloba
RNG *rng, ShaderData *sd, ShaderData *indirect_sd, ShaderData *emission_sd,
float3 throughput, float num_samples_adjust, PathState *state, PathRadiance *L)
{
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- const ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
if(!CLOSURE_IS_BSDF(sc->type))
continue;
@@ -140,14 +144,14 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
Ray *ray,
float3 throughput)
{
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = &ccl_fetch(sd, closure)[i];
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(!CLOSURE_IS_BSSRDF(sc->type))
continue;
/* set up random number generator */
- uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
RNG bssrdf_rng = cmj_hash(*rng, i);
@@ -169,7 +173,7 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
Ray volume_ray = *ray;
bool need_update_volume_stack =
kernel_data.integrator.use_volumes &&
- ccl_fetch(sd, object_flag) & SD_OBJECT_INTERSECTS_VOLUME;
+ sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
#endif /* __VOLUME__ */
/* compute lighting with the BSDF closure */
@@ -206,7 +210,8 @@ ccl_device void kernel_branched_path_subsurface_scatter(KernelGlobals *kg,
#ifdef __EMISSION__
/* direct light */
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_direct;
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (state->flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(
kg,
rng,
@@ -280,7 +285,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(rng, state.rng_offset, state.sample, 0x51633e2d);
}
bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -461,7 +466,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __BACKGROUND__
/* sample background shader */
float3 L_background = indirect_background(kg, &emission_sd, &state, &ray);
- path_radiance_accum_background(&L, throughput, L_background, state.bounce);
+ path_radiance_accum_background(&L, &state, throughput, L_background);
#endif /* __BACKGROUND__ */
break;
@@ -472,6 +477,21 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
shader_eval_surface(kg, &sd, rng, &state, 0.0f, state.flag, SHADER_CONTEXT_MAIN);
shader_merge_closures(&sd);
+#ifdef __SHADOW_TRICKS__
+ if((sd.object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if(state.flag & PATH_RAY_CAMERA) {
+ state.flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state.catcher_object = sd.object;
+ if(!kernel_data.background.transparent) {
+ L.shadow_color = indirect_background(kg, &emission_sd, &state, &ray);
+ }
+ }
+ }
+ else {
+ state.flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
+
/* holdout */
#ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) || (sd.object_flag & SD_OBJECT_HOLDOUT_MASK)) {
@@ -544,7 +564,8 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __EMISSION__
/* direct light */
if(kernel_data.integrator.use_direct_light) {
- int all = kernel_data.integrator.sample_all_lights_direct;
+ int all = (kernel_data.integrator.sample_all_lights_direct) ||
+ (state.flag & PATH_RAY_SHADOW_CATCHER);
kernel_branched_path_surface_connect_light(kg, rng,
&sd, &emission_sd, &hit_state, throughput, 1.0f, &L, all);
}
@@ -581,7 +602,16 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif /* __VOLUME__ */
}
- float3 L_sum = path_radiance_clamp_and_sum(kg, &L);
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state.flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, &L, &L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, &L);
+ }
kernel_write_light_passes(kg, buffer, &L, sample);
diff --git a/intern/cycles/kernel/kernel_path_common.h b/intern/cycles/kernel/kernel_path_common.h
index 7b903556bf9..82f83deb595 100644
--- a/intern/cycles/kernel/kernel_path_common.h
+++ b/intern/cycles/kernel/kernel_path_common.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "util_hash.h"
+#include "util/util_hash.h"
CCL_NAMESPACE_BEGIN
@@ -22,7 +22,7 @@ ccl_device_inline void kernel_path_trace_setup(KernelGlobals *kg,
ccl_global uint *rng_state,
int sample,
int x, int y,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ccl_addr_space Ray *ray)
{
float filter_u;
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index 661dc52fb31..c0cd2a63120 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void path_state_init(KernelGlobals *kg,
ShaderData *stack_sd,
ccl_addr_space PathState *state,
- ccl_addr_space RNG *rng,
+ RNG *rng,
int sample,
ccl_addr_space Ray *ray)
{
@@ -54,6 +54,10 @@ ccl_device_inline void path_state_init(KernelGlobals *kg,
state->volume_stack[0].shader = SHADER_NONE;
}
#endif
+
+#ifdef __SHADOW_TRICKS__
+ state->catcher_object = OBJECT_NONE;
+#endif
}
ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
diff --git a/intern/cycles/kernel/kernel_path_subsurface.h b/intern/cycles/kernel/kernel_path_subsurface.h
new file mode 100644
index 00000000000..10b568ac3dd
--- /dev/null
+++ b/intern/cycles/kernel/kernel_path_subsurface.h
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __SUBSURFACE__
+# ifndef __KERNEL_CUDA__
+ccl_device
+# else
+ccl_device_inline
+# endif
+bool kernel_path_subsurface_scatter(
+ KernelGlobals *kg,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ PathRadiance *L,
+ ccl_addr_space PathState *state,
+ RNG *rng,
+ ccl_addr_space Ray *ray,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
+{
+ float bssrdf_probability;
+ ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
+
+ /* modify throughput for picking bssrdf or bsdf */
+ *throughput *= bssrdf_probability;
+
+ /* do bssrdf scatter step if we picked a bssrdf closure */
+ if(sc) {
+ /* We should never have two consecutive BSSRDF bounces,
+ * the second one should be converted to a diffuse BSDF to
+ * avoid this.
+ */
+ kernel_assert(!ss_indirect->tracing);
+
+ uint lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0x68bc21eb);
+
+ SubsurfaceIntersection ss_isect;
+ float bssrdf_u, bssrdf_v;
+ path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ int num_hits = subsurface_scatter_multi_intersect(kg,
+ &ss_isect,
+ sd,
+ sc,
+ &lcg_state,
+ bssrdf_u, bssrdf_v,
+ false);
+# ifdef __VOLUME__
+ ss_indirect->need_update_volume_stack =
+ kernel_data.integrator.use_volumes &&
+ sd->object_flag & SD_OBJECT_INTERSECTS_VOLUME;
+# endif /* __VOLUME__ */
+
+ /* compute lighting with the BSDF closure */
+ for(int hit = 0; hit < num_hits; hit++) {
+ /* NOTE: We reuse the existing ShaderData, we assume the path
+ * integration loop stops when this function returns true.
+ */
+ subsurface_scatter_multi_setup(kg,
+ &ss_isect,
+ hit,
+ sd,
+ state,
+ state->flag,
+ sc,
+ false);
+
+ ccl_addr_space PathState *hit_state = &ss_indirect->state[ss_indirect->num_rays];
+ ccl_addr_space Ray *hit_ray = &ss_indirect->rays[ss_indirect->num_rays];
+ ccl_addr_space float3 *hit_tp = &ss_indirect->throughputs[ss_indirect->num_rays];
+ PathRadiance *hit_L = &ss_indirect->L[ss_indirect->num_rays];
+
+ *hit_state = *state;
+ *hit_ray = *ray;
+ *hit_tp = *throughput;
+
+ hit_state->rng_offset += PRNG_BOUNCE_NUM;
+
+ path_radiance_init(hit_L, kernel_data.film.use_light_pass);
+ hit_L->direct_throughput = L->direct_throughput;
+ path_radiance_copy_indirect(hit_L, L);
+
+ kernel_path_surface_connect_light(kg, rng, sd, emission_sd, *hit_tp, state, hit_L);
+
+ if(kernel_path_surface_bounce(kg,
+ rng,
+ sd,
+ hit_tp,
+ hit_state,
+ hit_L,
+ hit_ray))
+ {
+# ifdef __LAMP_MIS__
+ hit_state->ray_t = 0.0f;
+# endif /* __LAMP_MIS__ */
+
+# ifdef __VOLUME__
+ if(ss_indirect->need_update_volume_stack) {
+ Ray volume_ray = *ray;
+ /* Setup ray from previous surface point to the new one. */
+ volume_ray.D = normalize_len(hit_ray->P - volume_ray.P,
+ &volume_ray.t);
+
+ kernel_volume_stack_update_for_subsurface(
+ kg,
+ emission_sd,
+ &volume_ray,
+ hit_state->volume_stack);
+ }
+# endif /* __VOLUME__ */
+ path_radiance_reset_indirect(L);
+ ss_indirect->num_rays++;
+ }
+ else {
+ path_radiance_accum_sample(L, hit_L, 1);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+ccl_device_inline void kernel_path_subsurface_init_indirect(
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
+{
+ ss_indirect->tracing = false;
+ ss_indirect->num_rays = 0;
+}
+
+ccl_device void kernel_path_subsurface_accum_indirect(
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
+ PathRadiance *L)
+{
+ if(ss_indirect->tracing) {
+ path_radiance_sum_indirect(L);
+ path_radiance_accum_sample(&ss_indirect->direct_L, L, 1);
+ if(ss_indirect->num_rays == 0) {
+ *L = ss_indirect->direct_L;
+ }
+ }
+}
+
+ccl_device void kernel_path_subsurface_setup_indirect(
+ KernelGlobals *kg,
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect,
+ ccl_addr_space PathState *state,
+ ccl_addr_space Ray *ray,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput)
+{
+ if(!ss_indirect->tracing) {
+ ss_indirect->direct_L = *L;
+ }
+ ss_indirect->tracing = true;
+
+ /* Setup state, ray and throughput for indirect SSS rays. */
+ ss_indirect->num_rays--;
+
+ ccl_addr_space Ray *indirect_ray = &ss_indirect->rays[ss_indirect->num_rays];
+ PathRadiance *indirect_L = &ss_indirect->L[ss_indirect->num_rays];
+
+ *state = ss_indirect->state[ss_indirect->num_rays];
+ *ray = *indirect_ray;
+ *L = *indirect_L;
+ *throughput = ss_indirect->throughputs[ss_indirect->num_rays];
+
+ state->rng_offset += ss_indirect->num_rays * PRNG_BOUNCE_NUM;
+}
+
+#endif /* __SUBSURFACE__ */
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/kernel_path_surface.h b/intern/cycles/kernel/kernel_path_surface.h
index fea503d06e5..076c82f3853 100644
--- a/intern/cycles/kernel/kernel_path_surface.h
+++ b/intern/cycles/kernel/kernel_path_surface.h
@@ -16,16 +16,22 @@
CCL_NAMESPACE_BEGIN
-#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__)
-
+#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__)
/* branched path tracing: connect path directly to position on one or more lights and add it to L */
-ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, ShaderData *emission_sd, PathState *state, float3 throughput,
- float num_samples_adjust, PathRadiance *L, int sample_all_lights)
+ccl_device_noinline void kernel_branched_path_surface_connect_light(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ ccl_addr_space PathState *state,
+ float3 throughput,
+ float num_samples_adjust,
+ PathRadiance *L,
+ int sample_all_lights)
{
#ifdef __EMISSION__
/* sample illumination from lights to find path contribution */
- if(!(ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL))
+ if(!(sd->flag & SD_BSDF_HAS_EVAL))
return;
Ray light_ray;
@@ -33,7 +39,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
bool is_lamp;
# ifdef __OBJECT_MOTION__
- light_ray.time = ccl_fetch(sd, time);
+ light_ray.time = sd->time;
# endif
if(sample_all_lights) {
@@ -52,7 +58,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
float terminate = path_branched_rng_light_termination(kg, &lamp_rng, state, j, num_samples);
LightSample ls;
- if(lamp_light_sample(kg, i, light_u, light_v, ccl_fetch(sd, P), &ls)) {
+ if(lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls)) {
/* The sampling probability returned by lamp_light_sample assumes that all lights were sampled.
* However, this code only samples lamps, so if the scene also had mesh lights, the real probability is twice as high. */
if(kernel_data.integrator.pdf_triangles != 0.0f)
@@ -66,6 +72,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light);
+ }
}
}
}
@@ -87,7 +96,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
light_t = 0.5f*light_t;
LightSample ls;
- if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
+ if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* Same as above, probability needs to be corrected since the sampling was forced to select a mesh light. */
if(kernel_data.integrator.num_all_lights)
ls.pdf *= 2.0f;
@@ -100,6 +109,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_inv, &L_light);
+ }
}
}
}
@@ -113,7 +125,7 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
float terminate = path_state_rng_light_termination(kg, rng, state);
LightSample ls;
- if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
+ if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
/* sample random light */
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
@@ -123,6 +135,9 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
/* accumulate */
path_radiance_accum_light(L, throughput*num_samples_adjust, &L_light, shadow, num_samples_adjust, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput*num_samples_adjust, &L_light);
+ }
}
}
}
@@ -130,9 +145,17 @@ ccl_device_noinline void kernel_branched_path_surface_connect_light(KernelGlobal
}
/* branched path tracing: bounce off or through surface to with new direction stored in ray */
-ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, const ShaderClosure *sc, int sample, int num_samples,
- float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
+ccl_device bool kernel_branched_path_surface_bounce(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ const ShaderClosure *sc,
+ int sample,
+ int num_samples,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ Ray *ray)
{
/* sample BSDF */
float bsdf_pdf;
@@ -156,15 +179,15 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
path_state_next(kg, state, label);
/* setup ray */
- ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
+ ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
ray->D = normalize(bsdf_omega_in);
ray->t = FLT_MAX;
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = ccl_fetch(sd, dP);
+ ray->dP = sd->dP;
ray->dD = bsdf_domega_in;
#endif
#ifdef __OBJECT_MOTION__
- ray->time = ccl_fetch(sd, time);
+ ray->time = sd->time;
#endif
#ifdef __VOLUME__
@@ -188,15 +211,29 @@ ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg, RNG *rng,
#endif
-#ifndef __SPLIT_KERNEL__
/* path tracing: connect path directly to position on a light and add it to L */
-ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_addr_space RNG *rng,
+ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, RNG *rng,
ShaderData *sd, ShaderData *emission_sd, float3 throughput, ccl_addr_space PathState *state,
PathRadiance *L)
{
#ifdef __EMISSION__
- if(!(kernel_data.integrator.use_direct_light && (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL)))
+ if(!(kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)))
+ return;
+
+#ifdef __SHADOW_TRICKS__
+ if(state->flag & PATH_RAY_SHADOW_CATCHER) {
+ kernel_branched_path_surface_connect_light(kg,
+ rng,
+ sd,
+ emission_sd,
+ state,
+ throughput,
+ 1.0f,
+ L,
+ 1);
return;
+ }
+#endif
/* sample illumination from lights to find path contribution */
float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
@@ -208,11 +245,11 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
bool is_lamp;
#ifdef __OBJECT_MOTION__
- light_ray.time = ccl_fetch(sd, time);
+ light_ray.time = sd->time;
#endif
LightSample ls;
- if(light_sample(kg, light_t, light_u, light_v, ccl_fetch(sd, time), ccl_fetch(sd, P), state->bounce, &ls)) {
+ if(light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
float terminate = path_state_rng_light_termination(kg, rng, state);
if(direct_emission(kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* trace shadow ray */
@@ -222,15 +259,17 @@ ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg, ccl_
/* accumulate */
path_radiance_accum_light(L, throughput, &L_light, shadow, 1.0f, state->bounce, is_lamp);
}
+ else {
+ path_radiance_accum_total_light(L, throughput, &L_light);
+ }
}
}
#endif
}
-#endif
/* path tracing: bounce off or through surface to with new direction stored in ray */
ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
- ccl_addr_space RNG *rng,
+ RNG *rng,
ShaderData *sd,
ccl_addr_space float3 *throughput,
ccl_addr_space PathState *state,
@@ -238,7 +277,7 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
ccl_addr_space Ray *ray)
{
/* no BSDF? we can stop here */
- if(ccl_fetch(sd, flag) & SD_BSDF) {
+ if(sd->flag & SD_BSDF) {
/* sample BSDF */
float bsdf_pdf;
BsdfEval bsdf_eval;
@@ -270,16 +309,16 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
path_state_next(kg, state, label);
/* setup ray */
- ray->P = ray_offset(ccl_fetch(sd, P), (label & LABEL_TRANSMIT)? -ccl_fetch(sd, Ng): ccl_fetch(sd, Ng));
+ ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
ray->D = normalize(bsdf_omega_in);
if(state->bounce == 0)
- ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */
+ ray->t -= sd->ray_length; /* clipping works through transparent */
else
ray->t = FLT_MAX;
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = ccl_fetch(sd, dP);
+ ray->dP = sd->dP;
ray->dD = bsdf_domega_in;
#endif
@@ -291,21 +330,21 @@ ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
return true;
}
#ifdef __VOLUME__
- else if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME) {
+ else if(sd->flag & SD_HAS_ONLY_VOLUME) {
/* no surface shader but have a volume shader? act transparent */
/* update path state, count as transparent */
path_state_next(kg, state, LABEL_TRANSPARENT);
if(state->bounce == 0)
- ray->t -= ccl_fetch(sd, ray_length); /* clipping works through transparent */
+ ray->t -= sd->ray_length; /* clipping works through transparent */
else
ray->t = FLT_MAX;
/* setup ray position, direction stays unchanged */
- ray->P = ray_offset(ccl_fetch(sd, P), -ccl_fetch(sd, Ng));
+ ray->P = ray_offset(sd->P, -sd->Ng);
#ifdef __RAY_DIFFERENTIALS__
- ray->dP = ccl_fetch(sd, dP);
+ ray->dP = sd->dP;
#endif
/* enter/exit volume */
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 3d3b7385d8b..371f2c1c7cb 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -24,7 +24,7 @@ ccl_device_inline void kernel_path_volume_connect_light(
ShaderData *sd,
ShaderData *emission_sd,
float3 throughput,
- PathState *state,
+ ccl_addr_space PathState *state,
PathRadiance *L)
{
#ifdef __EMISSION__
@@ -59,7 +59,7 @@ ccl_device_inline void kernel_path_volume_connect_light(
}
}
}
-#endif
+#endif /* __EMISSION__ */
}
#ifdef __KERNEL_GPU__
@@ -67,8 +67,14 @@ ccl_device_noinline
#else
ccl_device
#endif
-bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
+bool kernel_path_volume_bounce(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ ccl_addr_space float3 *throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ ccl_addr_space Ray *ray)
{
/* sample phase function */
float phase_pdf;
@@ -111,9 +117,18 @@ bool kernel_path_volume_bounce(KernelGlobals *kg, RNG *rng,
return true;
}
-ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG *rng,
- ShaderData *sd, ShaderData *emission_sd, float3 throughput, PathState *state, PathRadiance *L,
- bool sample_all_lights, Ray *ray, const VolumeSegment *segment)
+#ifndef __SPLIT_KERNEL__
+ccl_device void kernel_branched_path_volume_connect_light(
+ KernelGlobals *kg,
+ RNG *rng,
+ ShaderData *sd,
+ ShaderData *emission_sd,
+ float3 throughput,
+ ccl_addr_space PathState *state,
+ PathRadiance *L,
+ bool sample_all_lights,
+ Ray *ray,
+ const VolumeSegment *segment)
{
#ifdef __EMISSION__
if(!kernel_data.integrator.use_direct_light)
@@ -261,10 +276,11 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
}
}
}
-#endif
+#endif /* __EMISSION__ */
}
+#endif /* __SPLIT_KERNEL__ */
-#endif
+#endif /* __VOLUME_SCATTER__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_queues.h b/intern/cycles/kernel/kernel_queues.h
index cf5614b8a86..96bc636d5ac 100644
--- a/intern/cycles/kernel/kernel_queues.h
+++ b/intern/cycles/kernel/kernel_queues.h
@@ -17,12 +17,15 @@
#ifndef __KERNEL_QUEUE_H__
#define __KERNEL_QUEUE_H__
+CCL_NAMESPACE_BEGIN
+
/*
* Queue utility functions for split kernel
*/
-
+#ifdef __KERNEL_OPENCL__
#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
+#endif
/*
* Enqueue ray index into the queue
@@ -35,7 +38,8 @@ ccl_device void enqueue_ray_index(
ccl_global int *queue_index) /* Array of size num_queues; Used for atomic increment. */
{
/* This thread's queue index. */
- int my_queue_index = atomic_inc(&queue_index[queue_number]) + (queue_number * queue_size);
+ int my_queue_index = atomic_fetch_and_inc_uint32((ccl_global uint*)&queue_index[queue_number])
+ + (queue_number * queue_size);
queues[my_queue_index] = ray_index;
}
@@ -47,6 +51,7 @@ ccl_device void enqueue_ray_index(
* is no more ray to allocate to other threads.
*/
ccl_device int get_ray_index(
+ KernelGlobals *kg,
int thread_index, /* Global thread index. */
int queue_number, /* Queue to operate on. */
ccl_global int *queues, /* Buffer of all queues. */
@@ -68,24 +73,25 @@ ccl_device void enqueue_ray_index_local(
int queue_number, /* Queue in which to enqueue ray index. */
char enqueue_flag, /* True for threads whose ray index has to be enqueued. */
int queuesize, /* queue size. */
- ccl_local unsigned int *local_queue_atomics, /* To to local queue atomics. */
+ ccl_local_param unsigned int *local_queue_atomics, /* To to local queue atomics. */
ccl_global int *Queue_data, /* Queues. */
ccl_global int *Queue_index) /* To do global queue atomics. */
{
- int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0);
+ int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
/* Get local queue id .*/
unsigned int lqidx;
if(enqueue_flag) {
- lqidx = atomic_inc(local_queue_atomics);
+ lqidx = atomic_fetch_and_inc_uint32(local_queue_atomics);
}
- barrier(CLK_LOCAL_MEM_FENCE);
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
/* Get global queue offset. */
if(lidx == 0) {
- *local_queue_atomics = atomic_add(&Queue_index[queue_number], *local_queue_atomics);
+ *local_queue_atomics = atomic_fetch_and_add_uint32((ccl_global uint*)&Queue_index[queue_number],
+ *local_queue_atomics);
}
- barrier(CLK_LOCAL_MEM_FENCE);
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
/* Get global queue index and enqueue ray. */
if(enqueue_flag) {
@@ -96,19 +102,19 @@ ccl_device void enqueue_ray_index_local(
ccl_device unsigned int get_local_queue_index(
int queue_number, /* Queue in which to enqueue the ray; -1 if no queue */
- ccl_local unsigned int *local_queue_atomics)
+ ccl_local_param unsigned int *local_queue_atomics)
{
- int my_lqidx = atomic_inc(&local_queue_atomics[queue_number]);
+ int my_lqidx = atomic_fetch_and_inc_uint32(&local_queue_atomics[queue_number]);
return my_lqidx;
}
ccl_device unsigned int get_global_per_queue_offset(
int queue_number,
- ccl_local unsigned int *local_queue_atomics,
+ ccl_local_param unsigned int *local_queue_atomics,
ccl_global int* global_queue_atomics)
{
- unsigned int queue_offset = atomic_add(&global_queue_atomics[queue_number],
- local_queue_atomics[queue_number]);
+ unsigned int queue_offset = atomic_fetch_and_add_uint32((ccl_global uint*)&global_queue_atomics[queue_number],
+ local_queue_atomics[queue_number]);
return queue_offset;
}
@@ -116,10 +122,12 @@ ccl_device unsigned int get_global_queue_index(
int queue_number,
int queuesize,
unsigned int lqidx,
- ccl_local unsigned int * global_per_queue_offset)
+ ccl_local_param unsigned int * global_per_queue_offset)
{
int my_gqidx = queuesize * queue_number + lqidx + global_per_queue_offset[queue_number];
return my_gqidx;
}
+CCL_NAMESPACE_END
+
#endif // __KERNEL_QUEUE_H__
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index e773753396f..d4f0caff5de 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "kernel_jitter.h"
+#include "kernel/kernel_jitter.h"
CCL_NAMESPACE_BEGIN
@@ -98,7 +98,7 @@ ccl_device uint sobol_lookup(const uint m, const uint frame, const uint ex, cons
return index;
}
-ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension)
+ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -130,7 +130,7 @@ ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *
#endif
}
-ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
+ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
{
#ifdef __CMJ__
if(kernel_data.integrator.sampling_pattern == SAMPLING_PATTERN_CMJ) {
@@ -147,7 +147,7 @@ ccl_device_forceinline void path_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *r
}
}
-ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, ccl_addr_space RNG *rng, int x, int y, float *fx, float *fy)
+ccl_device_inline void path_rng_init(KernelGlobals *kg, ccl_global uint *rng_state, int sample, int num_samples, RNG *rng, int x, int y, float *fx, float *fy)
{
#ifdef __SOBOL_FULL_SCREEN__
uint px, py;
@@ -191,14 +191,14 @@ ccl_device void path_rng_end(KernelGlobals *kg, ccl_global uint *rng_state, RNG
/* Linear Congruential Generator */
-ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, RNG& rng, int sample, int num_samples, int dimension)
+ccl_device_forceinline float path_rng_1D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension)
{
/* implicit mod 2^32 */
- rng = (1103515245*(rng) + 12345);
- return (float)rng * (1.0f/(float)0xFFFFFFFF);
+ *rng = (1103515245*(*rng) + 12345);
+ return (float)*rng * (1.0f/(float)0xFFFFFFFF);
}
-ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG& rng, int sample, int num_samples, int dimension, float *fx, float *fy)
+ccl_device_inline void path_rng_2D(KernelGlobals *kg, RNG *rng, int sample, int num_samples, int dimension, float *fx, float *fy)
{
*fx = path_rng_1D(kg, rng, sample, num_samples, dimension);
*fy = path_rng_1D(kg, rng, sample, num_samples, dimension + 1);
@@ -259,12 +259,12 @@ ccl_device uint lcg_init(uint seed)
* For branches in the path we must be careful not to reuse the same number
* in a sequence and offset accordingly. */
-ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension);
}
-ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension)
+ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension)
{
/* the rng_offset is not increased for transparent bounces. if we do then
* fully transparent objects can become subtly visible by the different
@@ -277,29 +277,29 @@ ccl_device_inline float path_state_rng_1D_for_decision(KernelGlobals *kg, ccl_ad
return path_rng_1D(kg, rng, state->sample, state->num_samples, rng_offset + dimension);
}
-ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
+ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy);
}
-ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension);
}
-ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension)
+ccl_device_inline float path_branched_rng_1D_for_decision(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
{
int rng_offset = state->rng_offset + state->transparent_bounce*PRNG_BOUNCE_NUM;
return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, rng_offset + dimension);
}
-ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
+ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
{
path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy);
}
/* Utitility functions to get light termination value, since it might not be needed in many cases. */
-ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const ccl_addr_space PathState *state)
+ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_state_rng_1D_for_decision(kg, rng, state, PRNG_LIGHT_TERMINATE);
@@ -307,7 +307,7 @@ ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, ccl_
return 0.0f;
}
-ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, ccl_addr_space RNG *rng, const PathState *state, int branch, int num_branches)
+ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, RNG *rng, const ccl_addr_space PathState *state, int branch, int num_branches)
{
if(kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
return path_branched_rng_1D_for_decision(kg, rng, state, branch, num_branches, PRNG_LIGHT_TERMINATE);
@@ -315,7 +315,7 @@ ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, c
return 0.0f;
}
-ccl_device_inline void path_state_branch(PathState *state, int branch, int num_branches)
+ccl_device_inline void path_state_branch(ccl_addr_space PathState *state, int branch, int num_branches)
{
/* path is splitting into a branch, adjust so that each branch
* still gets a unique sample from the same sequence */
@@ -324,18 +324,9 @@ ccl_device_inline void path_state_branch(PathState *state, int branch, int num_b
state->num_samples = state->num_samples*num_branches;
}
-ccl_device_inline uint lcg_state_init(RNG *rng, const PathState *state, uint scramble)
-{
- return lcg_init(*rng + state->rng_offset + state->sample*scramble);
-}
-
-/* TODO(sergey): For until we can use generic address space from OpenCL 2.0. */
-
-ccl_device_inline uint lcg_state_init_addrspace(ccl_addr_space RNG *rng,
- const ccl_addr_space PathState *state,
- uint scramble)
+ccl_device_inline uint lcg_state_init(RNG *rng, int rng_offset, int sample, uint scramble)
{
- return lcg_init(*rng + state->rng_offset + state->sample*scramble);
+ return lcg_init(*rng + rng_offset + sample*scramble);
}
ccl_device float lcg_step_float_addrspace(ccl_addr_space uint *rng)
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index d0826e5e879..8c0c5e90a3e 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -24,12 +24,12 @@
*
*/
-#include "closure/alloc.h"
-#include "closure/bsdf_util.h"
-#include "closure/bsdf.h"
-#include "closure/emissive.h"
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_util.h"
+#include "kernel/closure/bsdf.h"
+#include "kernel/closure/emissive.h"
-#include "svm/svm.h"
+#include "kernel/svm/svm.h"
CCL_NAMESPACE_BEGIN
@@ -38,13 +38,13 @@ CCL_NAMESPACE_BEGIN
#ifdef __OBJECT_MOTION__
ccl_device void shader_setup_object_transforms(KernelGlobals *kg, ShaderData *sd, float time)
{
- if(ccl_fetch(sd, object_flag) & SD_OBJECT_MOTION) {
- ccl_fetch(sd, ob_tfm) = object_fetch_transform_motion(kg, ccl_fetch(sd, object), time);
- ccl_fetch(sd, ob_itfm) = transform_quick_inverse(ccl_fetch(sd, ob_tfm));
+ if(sd->object_flag & SD_OBJECT_MOTION) {
+ sd->ob_tfm = object_fetch_transform_motion(kg, sd->object, time);
+ sd->ob_itfm = transform_quick_inverse(sd->ob_tfm);
}
else {
- ccl_fetch(sd, ob_tfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_TRANSFORM);
- ccl_fetch(sd, ob_itfm) = object_fetch_transform(kg, ccl_fetch(sd, object), OBJECT_INVERSE_TRANSFORM);
+ sd->ob_tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
+ sd->ob_itfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
}
}
#endif
@@ -55,55 +55,55 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
const Ray *ray)
{
#ifdef __INSTANCING__
- ccl_fetch(sd, object) = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
+ sd->object = (isect->object == PRIM_NONE)? kernel_tex_fetch(__prim_object, isect->prim): isect->object;
#endif
- ccl_fetch(sd, type) = isect->type;
- ccl_fetch(sd, flag) = 0;
- ccl_fetch(sd, object_flag) = kernel_tex_fetch(__object_flag,
- ccl_fetch(sd, object));
+ sd->type = isect->type;
+ sd->flag = 0;
+ sd->object_flag = kernel_tex_fetch(__object_flag,
+ sd->object);
/* matrices and time */
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, ray->time);
- ccl_fetch(sd, time) = ray->time;
+ sd->time = ray->time;
#endif
- ccl_fetch(sd, prim) = kernel_tex_fetch(__prim_index, isect->prim);
- ccl_fetch(sd, ray_length) = isect->t;
+ sd->prim = kernel_tex_fetch(__prim_index, isect->prim);
+ sd->ray_length = isect->t;
#ifdef __UV__
- ccl_fetch(sd, u) = isect->u;
- ccl_fetch(sd, v) = isect->v;
+ sd->u = isect->u;
+ sd->v = isect->v;
#endif
#ifdef __HAIR__
- if(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ if(sd->type & PRIMITIVE_ALL_CURVE) {
/* curve */
- float4 curvedata = kernel_tex_fetch(__curves, ccl_fetch(sd, prim));
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- ccl_fetch(sd, shader) = __float_as_int(curvedata.z);
- ccl_fetch(sd, P) = bvh_curve_refine(kg, sd, isect, ray);
+ sd->shader = __float_as_int(curvedata.z);
+ sd->P = bvh_curve_refine(kg, sd, isect, ray);
}
else
#endif
- if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
+ if(sd->type & PRIMITIVE_TRIANGLE) {
/* static triangle */
float3 Ng = triangle_normal(kg, sd);
- ccl_fetch(sd, shader) = kernel_tex_fetch(__tri_shader, ccl_fetch(sd, prim));
+ sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* vectors */
- ccl_fetch(sd, P) = triangle_refine(kg, sd, isect, ray);
- ccl_fetch(sd, Ng) = Ng;
- ccl_fetch(sd, N) = Ng;
+ sd->P = triangle_refine(kg, sd, isect, ray);
+ sd->Ng = Ng;
+ sd->N = Ng;
/* smooth normal */
- if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL)
- ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
+ if(sd->shader & SHADER_SMOOTH_NORMAL)
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __DPDU__
/* dPdu/dPdv */
- triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
+ triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif
}
else {
@@ -111,40 +111,40 @@ ccl_device_noinline void shader_setup_from_ray(KernelGlobals *kg,
motion_triangle_shader_setup(kg, sd, isect, ray, false);
}
- ccl_fetch(sd, I) = -ray->D;
+ sd->I = -ray->D;
- ccl_fetch(sd, flag) |= kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
+ sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
#ifdef __INSTANCING__
if(isect->object != OBJECT_NONE) {
/* instance transform */
- object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
- object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng));
+ object_normal_transform_auto(kg, sd, &sd->N);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
# ifdef __DPDU__
- object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
- object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
# endif
}
#endif
/* backfacing test */
- bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f);
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
if(backfacing) {
- ccl_fetch(sd, flag) |= SD_BACKFACING;
- ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng);
- ccl_fetch(sd, N) = -ccl_fetch(sd, N);
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
#ifdef __DPDU__
- ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu);
- ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv);
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
#endif
}
#ifdef __RAY_DIFFERENTIALS__
/* differentials */
- differential_transfer(&ccl_fetch(sd, dP), ray->dP, ray->D, ray->dD, ccl_fetch(sd, Ng), isect->t);
- differential_incoming(&ccl_fetch(sd, dI), ray->dD);
- differential_dudv(&ccl_fetch(sd, du), &ccl_fetch(sd, dv), ccl_fetch(sd, dPdu), ccl_fetch(sd, dPdv), ccl_fetch(sd, dP), ccl_fetch(sd, Ng));
+ differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
+ differential_incoming(&sd->dI, ray->dD);
+ differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
#endif
}
@@ -203,11 +203,11 @@ void shader_setup_from_subsurface(
# ifdef __INSTANCING__
if(isect->object != OBJECT_NONE) {
/* instance transform */
- object_normal_transform(kg, sd, &sd->N);
- object_normal_transform(kg, sd, &sd->Ng);
+ object_normal_transform_auto(kg, sd, &sd->N);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
# ifdef __DPDU__
- object_dir_transform(kg, sd, &sd->dPdu);
- object_dir_transform(kg, sd, &sd->dPdv);
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
# endif
}
# endif
@@ -249,106 +249,106 @@ ccl_device_inline void shader_setup_from_sample(KernelGlobals *kg,
int lamp)
{
/* vectors */
- ccl_fetch(sd, P) = P;
- ccl_fetch(sd, N) = Ng;
- ccl_fetch(sd, Ng) = Ng;
- ccl_fetch(sd, I) = I;
- ccl_fetch(sd, shader) = shader;
+ sd->P = P;
+ sd->N = Ng;
+ sd->Ng = Ng;
+ sd->I = I;
+ sd->shader = shader;
if(prim != PRIM_NONE)
- ccl_fetch(sd, type) = PRIMITIVE_TRIANGLE;
+ sd->type = PRIMITIVE_TRIANGLE;
else if(lamp != LAMP_NONE)
- ccl_fetch(sd, type) = PRIMITIVE_LAMP;
+ sd->type = PRIMITIVE_LAMP;
else
- ccl_fetch(sd, type) = PRIMITIVE_NONE;
+ sd->type = PRIMITIVE_NONE;
/* primitive */
#ifdef __INSTANCING__
- ccl_fetch(sd, object) = object;
+ sd->object = object;
#endif
/* currently no access to bvh prim index for strand sd->prim*/
- ccl_fetch(sd, prim) = prim;
+ sd->prim = prim;
#ifdef __UV__
- ccl_fetch(sd, u) = u;
- ccl_fetch(sd, v) = v;
+ sd->u = u;
+ sd->v = v;
#endif
- ccl_fetch(sd, ray_length) = t;
+ sd->ray_length = t;
- ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
- ccl_fetch(sd, object_flag) = 0;
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
- ccl_fetch(sd, object_flag) |= kernel_tex_fetch(__object_flag,
- ccl_fetch(sd, object));
+ sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
+ sd->object_flag = 0;
+ if(sd->object != OBJECT_NONE) {
+ sd->object_flag |= kernel_tex_fetch(__object_flag,
+ sd->object);
#ifdef __OBJECT_MOTION__
shader_setup_object_transforms(kg, sd, time);
- ccl_fetch(sd, time) = time;
+ sd->time = time;
}
else if(lamp != LAMP_NONE) {
- ccl_fetch(sd, ob_tfm) = lamp_fetch_transform(kg, lamp, false);
- ccl_fetch(sd, ob_itfm) = lamp_fetch_transform(kg, lamp, true);
+ sd->ob_tfm = lamp_fetch_transform(kg, lamp, false);
+ sd->ob_itfm = lamp_fetch_transform(kg, lamp, true);
#endif
}
/* transform into world space */
if(object_space) {
- object_position_transform_auto(kg, sd, &ccl_fetch(sd, P));
- object_normal_transform_auto(kg, sd, &ccl_fetch(sd, Ng));
- ccl_fetch(sd, N) = ccl_fetch(sd, Ng);
- object_dir_transform_auto(kg, sd, &ccl_fetch(sd, I));
+ object_position_transform_auto(kg, sd, &sd->P);
+ object_normal_transform_auto(kg, sd, &sd->Ng);
+ sd->N = sd->Ng;
+ object_dir_transform_auto(kg, sd, &sd->I);
}
- if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
+ if(sd->type & PRIMITIVE_TRIANGLE) {
/* smooth normal */
- if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
- ccl_fetch(sd, N) = triangle_smooth_normal(kg, ccl_fetch(sd, prim), ccl_fetch(sd, u), ccl_fetch(sd, v));
+ if(sd->shader & SHADER_SMOOTH_NORMAL) {
+ sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
#ifdef __INSTANCING__
- if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_normal_transform_auto(kg, sd, &ccl_fetch(sd, N));
+ if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_normal_transform_auto(kg, sd, &sd->N);
}
#endif
}
/* dPdu/dPdv */
#ifdef __DPDU__
- triangle_dPdudv(kg, ccl_fetch(sd, prim), &ccl_fetch(sd, dPdu), &ccl_fetch(sd, dPdv));
+ triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
# ifdef __INSTANCING__
- if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
- object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdu));
- object_dir_transform_auto(kg, sd, &ccl_fetch(sd, dPdv));
+ if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
+ object_dir_transform_auto(kg, sd, &sd->dPdu);
+ object_dir_transform_auto(kg, sd, &sd->dPdv);
}
# endif
#endif
}
else {
#ifdef __DPDU__
- ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f);
- ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* backfacing test */
- if(ccl_fetch(sd, prim) != PRIM_NONE) {
- bool backfacing = (dot(ccl_fetch(sd, Ng), ccl_fetch(sd, I)) < 0.0f);
+ if(sd->prim != PRIM_NONE) {
+ bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
if(backfacing) {
- ccl_fetch(sd, flag) |= SD_BACKFACING;
- ccl_fetch(sd, Ng) = -ccl_fetch(sd, Ng);
- ccl_fetch(sd, N) = -ccl_fetch(sd, N);
+ sd->flag |= SD_BACKFACING;
+ sd->Ng = -sd->Ng;
+ sd->N = -sd->N;
#ifdef __DPDU__
- ccl_fetch(sd, dPdu) = -ccl_fetch(sd, dPdu);
- ccl_fetch(sd, dPdv) = -ccl_fetch(sd, dPdv);
+ sd->dPdu = -sd->dPdu;
+ sd->dPdv = -sd->dPdv;
#endif
}
}
#ifdef __RAY_DIFFERENTIALS__
/* no ray differentials here yet */
- ccl_fetch(sd, dP) = differential3_zero();
- ccl_fetch(sd, dI) = differential3_zero();
- ccl_fetch(sd, du) = differential_zero();
- ccl_fetch(sd, dv) = differential_zero();
+ sd->dP = differential3_zero();
+ sd->dI = differential3_zero();
+ sd->du = differential_zero();
+ sd->dv = differential_zero();
#endif
}
@@ -378,39 +378,39 @@ ccl_device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
ccl_device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
{
/* vectors */
- ccl_fetch(sd, P) = ray->D;
- ccl_fetch(sd, N) = -ray->D;
- ccl_fetch(sd, Ng) = -ray->D;
- ccl_fetch(sd, I) = -ray->D;
- ccl_fetch(sd, shader) = kernel_data.background.surface_shader;
- ccl_fetch(sd, flag) = kernel_tex_fetch(__shader_flag, (ccl_fetch(sd, shader) & SHADER_MASK)*SHADER_SIZE);
- ccl_fetch(sd, object_flag) = 0;
+ sd->P = ray->D;
+ sd->N = -ray->D;
+ sd->Ng = -ray->D;
+ sd->I = -ray->D;
+ sd->shader = kernel_data.background.surface_shader;
+ sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*SHADER_SIZE);
+ sd->object_flag = 0;
#ifdef __OBJECT_MOTION__
- ccl_fetch(sd, time) = ray->time;
+ sd->time = ray->time;
#endif
- ccl_fetch(sd, ray_length) = 0.0f;
+ sd->ray_length = 0.0f;
#ifdef __INSTANCING__
- ccl_fetch(sd, object) = PRIM_NONE;
+ sd->object = PRIM_NONE;
#endif
- ccl_fetch(sd, prim) = PRIM_NONE;
+ sd->prim = PRIM_NONE;
#ifdef __UV__
- ccl_fetch(sd, u) = 0.0f;
- ccl_fetch(sd, v) = 0.0f;
+ sd->u = 0.0f;
+ sd->v = 0.0f;
#endif
#ifdef __DPDU__
/* dPdu/dPdv */
- ccl_fetch(sd, dPdu) = make_float3(0.0f, 0.0f, 0.0f);
- ccl_fetch(sd, dPdv) = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
+ sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
#endif
#ifdef __RAY_DIFFERENTIALS__
/* differentials */
- ccl_fetch(sd, dP) = ray->dD;
- differential_incoming(&ccl_fetch(sd, dI), ccl_fetch(sd, dP));
- ccl_fetch(sd, du) = differential_zero();
- ccl_fetch(sd, dv) = differential_zero();
+ sd->dP = ray->dD;
+ differential_incoming(&sd->dI, sd->dP);
+ sd->du = differential_zero();
+ sd->dv = differential_zero();
#endif
}
@@ -505,18 +505,18 @@ ccl_device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, ShaderData *sd
{
/* this is the veach one-sample model with balance heuristic, some pdf
* factors drop out when using balance heuristic weighting */
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
+ for(int i = 0; i < sd->num_closure; i++) {
if(i == skip_bsdf)
continue;
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ const ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
if(bsdf_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval*sc->weight);
+ bsdf_eval_accum(result_eval, sc->type, eval*sc->weight, 1.0f);
sum_pdf += bsdf_pdf*sc->sample_weight;
}
@@ -535,8 +535,8 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
float light_pdf,
bool use_mis)
{
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF(sc->type)) {
float bsdf_pdf = 0.0f;
float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf);
@@ -544,7 +544,8 @@ ccl_device_inline void _shader_bsdf_multi_eval_branched(KernelGlobals *kg,
float mis_weight = use_mis? power_heuristic(light_pdf, bsdf_pdf): 1.0f;
bsdf_eval_accum(result_eval,
sc->type,
- eval * sc->weight * mis_weight);
+ eval * sc->weight,
+ mis_weight);
}
}
}
@@ -576,7 +577,7 @@ void shader_bsdf_eval(KernelGlobals *kg,
_shader_bsdf_multi_eval(kg, sd, omega_in, &pdf, -1, eval, 0.0f, 0.0f);
if(use_mis) {
float weight = power_heuristic(light_pdf, pdf);
- bsdf_eval_mul(eval, weight);
+ bsdf_eval_mis(eval, weight);
}
}
}
@@ -591,22 +592,22 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
{
int sampled = 0;
- if(ccl_fetch(sd, num_closure) > 1) {
+ if(sd->num_closure > 1) {
/* pick a BSDF closure based on sample weights */
float sum = 0.0f;
- for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) {
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
+ for(sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
if(CLOSURE_IS_BSDF(sc->type))
sum += sc->sample_weight;
}
- float r = ccl_fetch(sd, randb_closure)*sum;
+ float r = sd->randb_closure*sum;
sum = 0.0f;
- for(sampled = 0; sampled < ccl_fetch(sd, num_closure); sampled++) {
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
+ for(sampled = 0; sampled < sd->num_closure; sampled++) {
+ const ShaderClosure *sc = &sd->closure[sampled];
if(CLOSURE_IS_BSDF(sc->type)) {
sum += sc->sample_weight;
@@ -616,13 +617,13 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
}
}
- if(sampled == ccl_fetch(sd, num_closure)) {
+ if(sampled == sd->num_closure) {
*pdf = 0.0f;
return LABEL_NONE;
}
}
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, sampled);
+ const ShaderClosure *sc = &sd->closure[sampled];
int label;
float3 eval;
@@ -633,7 +634,7 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
if(*pdf != 0.0f) {
bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
- if(ccl_fetch(sd, num_closure) > 1) {
+ if(sd->num_closure > 1) {
float sweight = sc->sample_weight;
_shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
}
@@ -660,8 +661,8 @@ ccl_device int shader_bsdf_sample_closure(KernelGlobals *kg, ShaderData *sd,
ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
{
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF(sc->type))
bsdf_blur(kg, sc, roughness);
@@ -670,13 +671,13 @@ ccl_device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughn
ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
{
- if(ccl_fetch(sd, flag) & SD_HAS_ONLY_VOLUME)
+ if(sd->flag & SD_HAS_ONLY_VOLUME)
return make_float3(1.0f, 1.0f, 1.0f);
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
eval += sc->weight;
@@ -685,6 +686,18 @@ ccl_device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
return eval;
}
+ccl_device void shader_bsdf_disable_transparency(KernelGlobals *kg, ShaderData *sd)
+{
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
+
+ if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
+ sc->sample_weight = 0.0f;
+ sc->weight = make_float3(0.0f, 0.0f, 0.0f);
+ }
+ }
+}
+
ccl_device float3 shader_bsdf_alpha(KernelGlobals *kg, ShaderData *sd)
{
float3 alpha = make_float3(1.0f, 1.0f, 1.0f) - shader_bsdf_transparency(kg, sd);
@@ -699,8 +712,8 @@ ccl_device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
eval += sc->weight;
@@ -713,8 +726,8 @@ ccl_device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
eval += sc->weight;
@@ -727,8 +740,8 @@ ccl_device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
eval += sc->weight;
@@ -741,8 +754,8 @@ ccl_device float3 shader_bsdf_subsurface(KernelGlobals *kg, ShaderData *sd)
{
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSSRDF(sc->type) || CLOSURE_IS_BSDF_BSSRDF(sc->type))
eval += sc->weight;
@@ -756,8 +769,8 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
float3 N = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
const DiffuseBsdf *bsdf = (const DiffuseBsdf*)sc;
@@ -766,12 +779,12 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
}
else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
eval += sc->weight;
- N += ccl_fetch(sd, N)*average(sc->weight);
+ N += sd->N*average(sc->weight);
}
}
if(is_zero(N))
- N = ccl_fetch(sd, N);
+ N = sd->N;
else
N = normalize(N);
@@ -786,8 +799,8 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
float3 N = make_float3(0.0f, 0.0f, 0.0f);
float texture_blur = 0.0f, weight_sum = 0.0f;
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSSRDF(sc->type)) {
const Bssrdf *bssrdf = (const Bssrdf*)sc;
@@ -801,10 +814,10 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
}
if(N_)
- *N_ = (is_zero(N))? ccl_fetch(sd, N): normalize(N);
+ *N_ = (is_zero(N))? sd->N: normalize(N);
if(texture_blur_)
- *texture_blur_ = texture_blur/weight_sum;
+ *texture_blur_ = safe_divide(texture_blur, weight_sum);
return eval;
}
@@ -814,7 +827,7 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
ccl_device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc)
{
- return emissive_simple_eval(ccl_fetch(sd, Ng), ccl_fetch(sd, I));
+ return emissive_simple_eval(sd->Ng, sd->I);
}
ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
@@ -822,8 +835,8 @@ ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
float3 eval;
eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_EMISSION(sc->type))
eval += emissive_eval(kg, sd, sc)*sc->weight;
@@ -838,8 +851,8 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
{
float3 weight = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_HOLDOUT(sc->type))
weight += sc->weight;
@@ -850,12 +863,12 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
/* Surface Evaluation */
-ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_space RNG *rng,
+ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, RNG *rng,
ccl_addr_space PathState *state, float randb, int path_flag, ShaderContext ctx)
{
- ccl_fetch(sd, num_closure) = 0;
- ccl_fetch(sd, num_closure_extra) = 0;
- ccl_fetch(sd, randb_closure) = randb;
+ sd->num_closure = 0;
+ sd->num_closure_extra = 0;
+ sd->randb_closure = randb;
#ifdef __OSL__
if(kg->osl)
@@ -869,13 +882,13 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd,
sizeof(DiffuseBsdf),
make_float3(0.8f, 0.8f, 0.8f));
- bsdf->N = ccl_fetch(sd, N);
- ccl_fetch(sd, flag) |= bsdf_diffuse_setup(bsdf);
+ bsdf->N = sd->N;
+ sd->flag |= bsdf_diffuse_setup(bsdf);
#endif
}
- if(rng && (ccl_fetch(sd, flag) & SD_BSDF_NEEDS_LCG)) {
- ccl_fetch(sd, lcg_state) = lcg_state_init_addrspace(rng, state, 0xb4bc3953);
+ if(rng && (sd->flag & SD_BSDF_NEEDS_LCG)) {
+ sd->lcg_state = lcg_state_init(rng, state->rng_offset, state->sample, 0xb4bc3953);
}
}
@@ -884,9 +897,9 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, ccl_addr_
ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
ccl_addr_space PathState *state, int path_flag, ShaderContext ctx)
{
- ccl_fetch(sd, num_closure) = 0;
- ccl_fetch(sd, num_closure_extra) = 0;
- ccl_fetch(sd, randb_closure) = 0.0f;
+ sd->num_closure = 0;
+ sd->num_closure_extra = 0;
+ sd->randb_closure = 0.0f;
#ifdef __SVM__
#ifdef __OSL__
@@ -901,8 +914,8 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
- for(int i = 0; i < ccl_fetch(sd, num_closure); i++) {
- const ShaderClosure *sc = ccl_fetch_array(sd, closure, i);
+ for(int i = 0; i < sd->num_closure; i++) {
+ const ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BACKGROUND(sc->type))
eval += sc->weight;
@@ -932,7 +945,7 @@ ccl_device_inline void _shader_volume_phase_multi_eval(const ShaderData *sd, con
float3 eval = volume_phase_eval(sd, sc, omega_in, &phase_pdf);
if(phase_pdf != 0.0f) {
- bsdf_eval_accum(result_eval, sc->type, eval);
+ bsdf_eval_accum(result_eval, sc->type, eval, 1.0f);
sum_pdf += phase_pdf*sc->sample_weight;
}
@@ -1024,8 +1037,8 @@ ccl_device int shader_phase_sample_closure(KernelGlobals *kg, const ShaderData *
ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
ShaderData *sd,
- PathState *state,
- VolumeStack *stack,
+ ccl_addr_space PathState *state,
+ ccl_addr_space VolumeStack *stack,
int path_flag,
ShaderContext ctx)
{
@@ -1081,9 +1094,9 @@ ccl_device_inline void shader_eval_volume(KernelGlobals *kg,
ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderContext ctx)
{
- ccl_fetch(sd, num_closure) = 0;
- ccl_fetch(sd, num_closure_extra) = 0;
- ccl_fetch(sd, randb_closure) = 0.0f;
+ sd->num_closure = 0;
+ sd->num_closure_extra = 0;
+ sd->randb_closure = 0.0f;
/* this will modify sd->P */
#ifdef __SVM__
diff --git a/intern/cycles/kernel/kernel_shadow.h b/intern/cycles/kernel/kernel_shadow.h
index 2981f6ac566..0426e0a62c9 100644
--- a/intern/cycles/kernel/kernel_shadow.h
+++ b/intern/cycles/kernel/kernel_shadow.h
@@ -16,9 +16,84 @@
CCL_NAMESPACE_BEGIN
-#ifdef __SHADOW_RECORD_ALL__
+/* Attenuate throughput accordingly to the given intersection event.
+ * Returns true if the throughput is zero and traversal can be aborted.
+ */
+ccl_device_forceinline bool shadow_handle_transparent_isect(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+# ifdef __VOLUME__
+ ccl_addr_space struct PathState *volume_state,
+# endif
+ Intersection *isect,
+ Ray *ray,
+ float3 *throughput)
+{
+#ifdef __VOLUME__
+ /* Attenuation between last surface and next surface. */
+ if(volume_state->volume_stack[0].shader != SHADER_NONE) {
+ Ray segment_ray = *ray;
+ segment_ray.t = isect->t;
+ kernel_volume_shadow(kg,
+ shadow_sd,
+ volume_state,
+ &segment_ray,
+ throughput);
+ }
+#endif
+ /* Setup shader data at surface. */
+ shader_setup_from_ray(kg, shadow_sd, isect, ray);
+ /* Attenuation from transparent surface. */
+ if(!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
+ path_state_modify_bounce(state, true);
+ shader_eval_surface(kg,
+ shadow_sd,
+ NULL,
+ state,
+ 0.0f,
+ PATH_RAY_SHADOW,
+ SHADER_CONTEXT_SHADOW);
+ path_state_modify_bounce(state, false);
+ *throughput *= shader_bsdf_transparency(kg, shadow_sd);
+ }
+ /* Stop if all light is blocked. */
+ if(is_zero(*throughput)) {
+ return true;
+ }
+#ifdef __VOLUME__
+ /* Exit/enter volume. */
+ kernel_volume_stack_enter_exit(kg, shadow_sd, volume_state->volume_stack);
+#endif
+ return false;
+}
+
+/* Special version which only handles opaque shadows. */
+ccl_device bool shadow_blocked_opaque(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ Intersection *isect,
+ float3 *shadow)
+{
+ const bool blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+#ifdef __VOLUME__
+ if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
+ kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
+ }
+#endif
+ return blocked;
+}
-/* Shadow function to compute how much light is blocked, CPU variation.
+#ifdef __TRANSPARENT_SHADOWS__
+# ifdef __SHADOW_RECORD_ALL__
+/* Shadow function to compute how much light is blocked,
*
* We trace a single ray. If it hits any opaque surface, or more than a given
* number of transparent surfaces is hit, then we consider the geometry to be
@@ -36,261 +111,403 @@ CCL_NAMESPACE_BEGIN
* or there is a performance increase anyway due to avoiding the need to send
* two rays with transparent shadows.
*
- * This is CPU only because of qsort, and malloc or high stack space usage to
- * record all these intersections. */
+ * On CPU it'll handle all transparent bounces (by allocating storage for
+ * intersections when they don't fit into the stack storage).
+ *
+ * On GPU it'll only handle SHADOW_STACK_MAX_HITS-1 intersections, so this
+ * is something to be kept an eye on.
+ */
-#define STACK_MAX_HITS 64
+# define SHADOW_STACK_MAX_HITS 64
-ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *shadow_sd, PathState *state, Ray *ray, float3 *shadow)
+/* Actual logic with traversal loop implementation which is free from device
+ * specific tweaks.
+ *
+ * Note that hits array should be as big as max_hits+1.
+ */
+ccl_device bool shadow_blocked_transparent_all_loop(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const int skip_object,
+ Ray *ray,
+ Intersection *hits,
+ uint max_hits,
+ float3 *shadow)
{
- *shadow = make_float3(1.0f, 1.0f, 1.0f);
-
- if(ray->t == 0.0f)
- return false;
-
- bool blocked;
-
- if(kernel_data.integrator.transparent_shadows) {
- /* check transparent bounces here, for volume scatter which can do
- * lighting before surface path termination is checked */
- if(state->transparent_bounce >= kernel_data.integrator.transparent_max_bounce)
- return true;
-
- /* intersect to find an opaque surface, or record all transparent surface hits */
- Intersection hits_stack[STACK_MAX_HITS];
- Intersection *hits = hits_stack;
- const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
- uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
-
- /* prefer to use stack but use dynamic allocation if too deep max hits
- * we need max_hits + 1 storage space due to the logic in
- * scene_intersect_shadow_all which will first store and then check if
- * the limit is exceeded */
- if(max_hits + 1 > STACK_MAX_HITS) {
- if(kg->transparent_shadow_intersections == NULL) {
- kg->transparent_shadow_intersections =
- (Intersection*)malloc(sizeof(Intersection)*(transparent_max_bounce + 1));
+ /* Intersect to find an opaque surface, or record all transparent
+ * surface hits.
+ */
+ uint num_hits;
+ const bool blocked = scene_intersect_shadow_all(kg,
+ ray,
+ hits,
+ skip_object,
+ max_hits,
+ &num_hits);
+ /* If no opaque surface found but we did find transparent hits,
+ * shade them.
+ */
+ if(!blocked && num_hits > 0) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ float last_t = 0.0f;
+ int bounce = state->transparent_bounce;
+ Intersection *isect = hits;
+# ifdef __VOLUME__
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
+# else
+ PathState ps_object;
+ PathState *ps = &ps_object;
+# endif
+ *ps = *state;
+# endif
+ sort_intersections(hits, num_hits);
+ for(int hit = 0; hit < num_hits; hit++, isect++) {
+ /* Adjust intersection distance for moving ray forward. */
+ float new_t = isect->t;
+ isect->t -= last_t;
+ /* Skip hit if we did not move forward, step by step raytracing
+ * would have skipped it as well then.
+ */
+ if(last_t == new_t) {
+ continue;
}
- hits = kg->transparent_shadow_intersections;
- }
-
- uint num_hits;
- blocked = scene_intersect_shadow_all(kg, ray, hits, max_hits, &num_hits);
-
- /* if no opaque surface found but we did find transparent hits, shade them */
- if(!blocked && num_hits > 0) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- float last_t = 0.0f;
- int bounce = state->transparent_bounce;
- Intersection *isect = hits;
+ last_t = new_t;
+ /* Attenuate the throughput. */
+ if(shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
#ifdef __VOLUME__
- PathState ps = *state;
+ ps,
#endif
-
- qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
-
- for(int hit = 0; hit < num_hits; hit++, isect++) {
- /* adjust intersection distance for moving ray forward */
- float new_t = isect->t;
- isect->t -= last_t;
-
- /* skip hit if we did not move forward, step by step raytracing
- * would have skipped it as well then */
- if(last_t == new_t)
- continue;
-
- last_t = new_t;
-
-#ifdef __VOLUME__
- /* attenuation between last surface and next surface */
- if(ps.volume_stack[0].shader != SHADER_NONE) {
- Ray segment_ray = *ray;
- segment_ray.t = isect->t;
- kernel_volume_shadow(kg, shadow_sd, &ps, &segment_ray, &throughput);
- }
-#endif
-
- /* setup shader data at surface */
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
-
- /* attenuation from transparent surface */
- if(!(shadow_sd->flag & SD_HAS_ONLY_VOLUME)) {
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
- path_state_modify_bounce(state, false);
-
- throughput *= shader_bsdf_transparency(kg, shadow_sd);
- }
-
- /* stop if all light is blocked */
- if(is_zero(throughput)) {
- return true;
- }
-
- /* move ray forward */
- ray->P = shadow_sd->P;
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
-
-#ifdef __VOLUME__
- /* exit/enter volume */
- kernel_volume_stack_enter_exit(kg, shadow_sd, ps.volume_stack);
-#endif
-
- bounce++;
+ isect,
+ ray,
+ &throughput))
+ {
+ return true;
}
-
-#ifdef __VOLUME__
- /* attenuation for last line segment towards light */
- if(ps.volume_stack[0].shader != SHADER_NONE)
- kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
-#endif
-
- *shadow = throughput;
-
- return is_zero(throughput);
+ /* Move ray forward. */
+ ray->P = shadow_sd->P;
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
}
+# ifdef __VOLUME__
+ /* Attenuation for last line segment towards light. */
+ if(ps->volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
+ }
+# endif
+ *shadow = throughput;
+ return is_zero(throughput);
}
- else {
- Intersection isect;
- blocked = scene_intersect(kg, *ray, PATH_RAY_SHADOW_OPAQUE, &isect, NULL, 0.0f, 0.0f);
- }
-
-#ifdef __VOLUME__
+# ifdef __VOLUME__
if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* apply attenuation from current volume shader */
+ /* Apply attenuation from current volume shader/ */
kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
}
-#endif
-
+# endif
return blocked;
}
-#undef STACK_MAX_HITS
-
-#else
+/* Here we do all device specific trickery before invoking actual traversal
+ * loop to help readability of the actual logic.
+ */
+ccl_device bool shadow_blocked_transparent_all(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const int skip_object,
+ Ray *ray,
+ uint max_hits,
+ float3 *shadow)
+{
+# ifdef __SPLIT_KERNEL__
+ Intersection hits_[SHADOW_STACK_MAX_HITS];
+ Intersection *hits = &hits_[0];
+# elif defined(__KERNEL_CUDA__)
+ Intersection *hits = kg->hits_stack;
+# else
+ Intersection hits_stack[SHADOW_STACK_MAX_HITS];
+ Intersection *hits = hits_stack;
+# endif
+# ifndef __KERNEL_GPU__
+ /* Prefer to use stack but use dynamic allocation if too deep max hits
+ * we need max_hits + 1 storage space due to the logic in
+ * scene_intersect_shadow_all which will first store and then check if
+ * the limit is exceeded.
+ *
+ * Ignore this on GPU because of slow/unavailable malloc().
+ */
+ if(max_hits + 1 > SHADOW_STACK_MAX_HITS) {
+ if(kg->transparent_shadow_intersections == NULL) {
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ kg->transparent_shadow_intersections =
+ (Intersection*)malloc(sizeof(Intersection)*(transparent_max_bounce + 1));
+ }
+ hits = kg->transparent_shadow_intersections;
+ }
+# endif /* __KERNEL_GPU__ */
+ /* Invoke actual traversal. */
+ return shadow_blocked_transparent_all_loop(kg,
+ shadow_sd,
+ state,
+ skip_object,
+ ray,
+ hits,
+ max_hits,
+ shadow);
+}
+# endif /* __SHADOW_RECORD_ALL__ */
-/* Shadow function to compute how much light is blocked, GPU variation.
+# if defined(__KERNEL_GPU__) || !defined(__SHADOW_RECORD_ALL__)
+/* Shadow function to compute how much light is blocked,
*
* Here we raytrace from one transparent surface to the next step by step.
* To minimize overhead in cases where we don't need transparent shadows, we
* first trace a regular shadow ray. We check if the hit primitive was
* potentially transparent, and only in that case start marching. this gives
- * one extra ray cast for the cases were we do want transparency. */
+ * one extra ray cast for the cases were we do want transparency.
+ */
-ccl_device_noinline bool shadow_blocked(KernelGlobals *kg,
- ShaderData *shadow_sd,
- ccl_addr_space PathState *state,
- ccl_addr_space Ray *ray_input,
- float3 *shadow)
+/* This function is only implementing device-independent traversal logic
+ * which requires some precalculation done.
+ */
+ccl_device bool shadow_blocked_transparent_stepped_loop(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const int skip_object,
+ Ray *ray,
+ Intersection *isect,
+ const bool blocked,
+ const bool is_transparent_isect,
+ float3 *shadow)
{
- *shadow = make_float3(1.0f, 1.0f, 1.0f);
-
- if(ray_input->t == 0.0f)
- return false;
-
-#ifdef __SPLIT_KERNEL__
- Ray private_ray = *ray_input;
- Ray *ray = &private_ray;
-#else
- Ray *ray = ray_input;
-#endif
-
-#ifdef __SPLIT_KERNEL__
- Intersection *isect = &kg->isect_shadow[SD_THREAD];
-#else
- Intersection isect_object;
- Intersection *isect = &isect_object;
-#endif
-
- bool blocked = scene_intersect(kg, *ray, PATH_RAY_SHADOW_OPAQUE, isect, NULL, 0.0f, 0.0f);
-
-#ifdef __TRANSPARENT_SHADOWS__
- if(blocked && kernel_data.integrator.transparent_shadows) {
- if(shader_transparent_shadow(kg, isect)) {
- float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
- float3 Pend = ray->P + ray->D*ray->t;
- int bounce = state->transparent_bounce;
-#ifdef __VOLUME__
- PathState ps = *state;
-#endif
-
- for(;;) {
- if(bounce >= kernel_data.integrator.transparent_max_bounce)
- return true;
-
- if(!scene_intersect(kg, *ray, PATH_RAY_SHADOW_TRANSPARENT, isect, NULL, 0.0f, 0.0f))
- {
-#ifdef __VOLUME__
- /* attenuation for last line segment towards light */
- if(ps.volume_stack[0].shader != SHADER_NONE)
- kernel_volume_shadow(kg, shadow_sd, &ps, ray, &throughput);
-#endif
-
- *shadow *= throughput;
-
- return false;
- }
-
- if(!shader_transparent_shadow(kg, isect)) {
- return true;
- }
-
-#ifdef __VOLUME__
- /* attenuation between last surface and next surface */
- if(ps.volume_stack[0].shader != SHADER_NONE) {
- Ray segment_ray = *ray;
- segment_ray.t = isect->t;
- kernel_volume_shadow(kg, shadow_sd, &ps, &segment_ray, &throughput);
+ if((blocked && is_transparent_isect) || skip_object != OBJECT_NONE) {
+ float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
+ float3 Pend = ray->P + ray->D*ray->t;
+ int bounce = state->transparent_bounce;
+# ifdef __VOLUME__
+# ifdef __SPLIT_KERNEL__
+ ccl_addr_space PathState *ps = &kernel_split_state.state_shadow[ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0)];
+# else
+ PathState ps_object;
+ PathState *ps = &ps_object;
+# endif
+ *ps = *state;
+# endif
+ for(;;) {
+ if(bounce >= kernel_data.integrator.transparent_max_bounce) {
+ return true;
+ }
+ if(!scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_TRANSPARENT,
+ isect,
+ NULL,
+ 0.0f, 0.0f))
+ {
+ break;
+ }
+#ifdef __SHADOW_TRICKS__
+ if(skip_object != OBJECT_NONE) {
+ const int isect_object = (isect->object == PRIM_NONE)
+ ? kernel_tex_fetch(__prim_object, isect->prim)
+ : isect->object;
+ if(isect_object == skip_object) {
+ shader_setup_from_ray(kg, shadow_sd, isect, ray);
+ /* Move ray forward. */
+ ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ continue;
}
+ }
#endif
-
- /* setup shader data at surface */
- shader_setup_from_ray(kg, shadow_sd, isect, ray);
-
- /* attenuation from transparent surface */
- if(!(ccl_fetch(shadow_sd, flag) & SD_HAS_ONLY_VOLUME)) {
- path_state_modify_bounce(state, true);
- shader_eval_surface(kg, shadow_sd, NULL, state, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW);
- path_state_modify_bounce(state, false);
-
- throughput *= shader_bsdf_transparency(kg, shadow_sd);
- }
-
- /* stop if all light is blocked */
- if(is_zero(throughput)) {
- return true;
- }
-
- /* move ray forward */
- ray->P = ray_offset(ccl_fetch(shadow_sd, P), -ccl_fetch(shadow_sd, Ng));
- if(ray->t != FLT_MAX) {
- ray->D = normalize_len(Pend - ray->P, &ray->t);
- }
-
+ if(!shader_transparent_shadow(kg, isect)) {
+ return true;
+ }
+ /* Attenuate the throughput. */
+ if(shadow_handle_transparent_isect(kg,
+ shadow_sd,
+ state,
#ifdef __VOLUME__
- /* exit/enter volume */
- kernel_volume_stack_enter_exit(kg, shadow_sd, ps.volume_stack);
+ ps,
#endif
-
- bounce++;
+ isect,
+ ray,
+ &throughput))
+ {
+ return true;
}
+ /* Move ray forward. */
+ ray->P = ray_offset(shadow_sd->P, -shadow_sd->Ng);
+ if(ray->t != FLT_MAX) {
+ ray->D = normalize_len(Pend - ray->P, &ray->t);
+ }
+ bounce++;
+ }
+# ifdef __VOLUME__
+ /* Attenuation for last line segment towards light. */
+ if(ps->volume_stack[0].shader != SHADER_NONE) {
+ kernel_volume_shadow(kg, shadow_sd, ps, ray, &throughput);
}
+# endif
+ *shadow *= throughput;
+ return is_zero(throughput);
}
-#ifdef __VOLUME__
- else if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
- /* apply attenuation from current volume shader */
+# ifdef __VOLUME__
+ if(!blocked && state->volume_stack[0].shader != SHADER_NONE) {
+ /* Apply attenuation from current volume shader. */
kernel_volume_shadow(kg, shadow_sd, state, ray, shadow);
}
-#endif
-#endif
-
+# endif
return blocked;
}
+ccl_device bool shadow_blocked_transparent_stepped(
+ KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ const int skip_object,
+ Ray *ray,
+ Intersection *isect,
+ float3 *shadow)
+{
+ bool blocked, is_transparent_isect;
+ if (skip_object == OBJECT_NONE) {
+ blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ isect,
+ NULL,
+ 0.0f, 0.0f);
+ is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, isect)
+ : false;
+ }
+ else {
+ blocked = false;
+ is_transparent_isect = false;
+ }
+ return shadow_blocked_transparent_stepped_loop(kg,
+ shadow_sd,
+ state,
+ skip_object,
+ ray,
+ isect,
+ blocked,
+ is_transparent_isect,
+ shadow);
+}
+
+# endif /* __KERNEL_GPU__ || !__SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
+
+ccl_device_inline bool shadow_blocked(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray_input,
+ float3 *shadow)
+{
+ Ray *ray = ray_input;
+ Intersection isect;
+ /* Some common early checks. */
+ *shadow = make_float3(1.0f, 1.0f, 1.0f);
+ if(ray->t == 0.0f) {
+ return false;
+ }
+#ifdef __SHADOW_TRICKS__
+ const int skip_object = state->catcher_object;
+#else
+ const int skip_object = OBJECT_NONE;
#endif
+ /* Do actual shadow shading. */
+ /* First of all, we check if integrator requires transparent shadows.
+ * if not, we use simplest and fastest ever way to calculate occlusion.
+ *
+ * NOTE: We can't do quick opaque test here if we are on shadow-catcher
+ * path because we don't want catcher object to be casting shadow here.
+ */
+#ifdef __TRANSPARENT_SHADOWS__
+ if(!kernel_data.integrator.transparent_shadows &&
+ skip_object == OBJECT_NONE)
+#endif
+ {
+ return shadow_blocked_opaque(kg,
+ shadow_sd,
+ state,
+ ray,
+ &isect,
+ shadow);
+ }
+#ifdef __TRANSPARENT_SHADOWS__
+# ifdef __SHADOW_RECORD_ALL__
+ /* For the transparent shadows we try to use record-all logic on the
+ * devices which supports this.
+ */
+ const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
+ /* Check transparent bounces here, for volume scatter which can do
+ * lighting before surface path termination is checked.
+ */
+ if(state->transparent_bounce >= transparent_max_bounce) {
+ return true;
+ }
+ const uint max_hits = transparent_max_bounce - state->transparent_bounce - 1;
+# ifdef __KERNEL_GPU__
+ /* On GPU we do trickey with tracing opaque ray first, this avoids speed
+ * regressions in some files.
+ *
+ * TODO(sergey): Check why using record-all behavior causes slowdown in such
+ * cases. Could that be caused by a higher spill pressure?
+ */
+ const bool blocked = scene_intersect(kg,
+ *ray,
+ PATH_RAY_SHADOW_OPAQUE,
+ &isect,
+ NULL,
+ 0.0f, 0.0f);
+ const bool is_transparent_isect = blocked
+ ? shader_transparent_shadow(kg, &isect)
+ : false;
+ if(!blocked || !is_transparent_isect ||
+ max_hits + 1 >= SHADOW_STACK_MAX_HITS)
+ {
+ return shadow_blocked_transparent_stepped_loop(kg,
+ shadow_sd,
+ state,
+ skip_object,
+ ray,
+ &isect,
+ blocked,
+ is_transparent_isect,
+ shadow);
+ }
+# endif /* __KERNEL_GPU__ */
+ return shadow_blocked_transparent_all(kg,
+ shadow_sd,
+ state,
+ skip_object,
+ ray,
+ max_hits,
+ shadow);
+# else /* __SHADOW_RECORD_ALL__ */
+ /* Fallback to a slowest version which works on all devices. */
+ return shadow_blocked_transparent_stepped(kg,
+ shadow_sd,
+ state,
+ skip_object,
+ ray,
+ &isect,
+ shadow);
+# endif /* __SHADOW_RECORD_ALL__ */
+#endif /* __TRANSPARENT_SHADOWS__ */
+}
-CCL_NAMESPACE_END
+#undef SHADOW_STACK_MAX_HITS
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h
index 52c05b85aee..f75e9337bdb 100644
--- a/intern/cycles/kernel/kernel_subsurface.h
+++ b/intern/cycles/kernel/kernel_subsurface.h
@@ -185,7 +185,7 @@ ccl_device float3 subsurface_color_pow(float3 color, float exponent)
ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
ShaderData *sd,
- PathState *state,
+ ccl_addr_space PathState *state,
int state_flag,
float3 *eval,
float3 *N)
@@ -223,7 +223,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
SubsurfaceIntersection *ss_isect,
ShaderData *sd,
ShaderClosure *sc,
- uint *lcg_state,
+ RNG *lcg_state,
float disk_u,
float disk_v,
bool all)
@@ -277,7 +277,12 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
float3 disk_P = (disk_r*cosf(phi)) * disk_T + (disk_r*sinf(phi)) * disk_B;
/* create ray */
+#ifdef __SPLIT_KERNEL__
+ Ray ray_object = ss_isect->ray;
+ Ray *ray = &ray_object;
+#else
Ray *ray = &ss_isect->ray;
+#endif
ray->P = sd->P + disk_N*disk_height + disk_P;
ray->D = -disk_N;
ray->t = 2.0f*disk_height;
@@ -288,7 +293,7 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
/* intersect with the same object. if multiple intersections are found it
* will use at most BSSRDF_MAX_HITS hits, a random subset of all hits */
scene_intersect_subsurface(kg,
- ray,
+ *ray,
ss_isect,
sd->object,
lcg_state,
@@ -298,20 +303,20 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
for(int hit = 0; hit < num_eval_hits; hit++) {
/* Quickly retrieve P and Ng without setting up ShaderData. */
float3 hit_P;
- if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE) {
+ if(sd->type & PRIMITIVE_TRIANGLE) {
hit_P = triangle_refine_subsurface(kg,
sd,
&ss_isect->hits[hit],
ray);
}
#ifdef __OBJECT_MOTION__
- else if(ccl_fetch(sd, type) & PRIMITIVE_MOTION_TRIANGLE) {
+ else if(sd->type & PRIMITIVE_MOTION_TRIANGLE) {
float3 verts[3];
motion_triangle_vertices(
kg,
- ccl_fetch(sd, object),
+ sd->object,
kernel_tex_fetch(__prim_index, ss_isect->hits[hit].prim),
- ccl_fetch(sd, time),
+ sd->time,
verts);
hit_P = motion_triangle_refine_subsurface(kg,
sd,
@@ -351,6 +356,10 @@ ccl_device_inline int subsurface_scatter_multi_intersect(
ss_isect->weight[hit] = eval;
}
+#ifdef __SPLIT_KERNEL__
+ ss_isect->ray = *ray;
+#endif
+
return num_eval_hits;
}
@@ -359,13 +368,19 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
SubsurfaceIntersection* ss_isect,
int hit,
ShaderData *sd,
- PathState *state,
+ ccl_addr_space PathState *state,
int state_flag,
ShaderClosure *sc,
bool all)
{
+#ifdef __SPLIT_KERNEL__
+ Ray ray_object = ss_isect->ray;
+ Ray *ray = &ray_object;
+#else
+ Ray *ray = &ss_isect->ray;
+#endif
/* Setup new shading point. */
- shader_setup_from_subsurface(kg, sd, &ss_isect->hits[hit], &ss_isect->ray);
+ shader_setup_from_subsurface(kg, sd, &ss_isect->hits[hit], ray);
/* Optionally blur colors and bump mapping. */
float3 weight = ss_isect->weight[hit];
@@ -376,6 +391,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
subsurface_scatter_setup_diffuse_bsdf(sd, weight, true, N);
}
+#ifndef __SPLIT_KERNEL__
/* subsurface scattering step, from a point on the surface to another nearby point on the same object */
ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathState *state,
int state_flag, ShaderClosure *sc, uint *lcg_state, float disk_u, float disk_v, bool all)
@@ -432,7 +448,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
/* intersect with the same object. if multiple intersections are
* found it will randomly pick one of them */
SubsurfaceIntersection ss_isect;
- scene_intersect_subsurface(kg, &ray, &ss_isect, sd->object, lcg_state, 1);
+ scene_intersect_subsurface(kg, ray, &ss_isect, sd->object, lcg_state, 1);
/* evaluate bssrdf */
if(ss_isect.num_hits > 0) {
@@ -465,6 +481,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
/* setup diffuse bsdf */
subsurface_scatter_setup_diffuse_bsdf(sd, eval, (ss_isect.num_hits > 0), N);
}
+#endif /* ! __SPLIT_KERNEL__ */
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h
index 8d5bb75a428..cb1a3f40dee 100644
--- a/intern/cycles/kernel/kernel_textures.h
+++ b/intern/cycles/kernel/kernel_textures.h
@@ -32,6 +32,7 @@ KERNEL_TEX(uint, texture_uint, __prim_visibility)
KERNEL_TEX(uint, texture_uint, __prim_index)
KERNEL_TEX(uint, texture_uint, __prim_object)
KERNEL_TEX(uint, texture_uint, __object_node)
+KERNEL_TEX(float2, texture_float2, __prim_time)
/* objects */
KERNEL_TEX(float4, texture_float4, __objects)
@@ -177,7 +178,6 @@ KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_085)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_086)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_087)
KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_088)
-KERNEL_IMAGE_TEX(uchar4, texture_image_uchar4, __tex_image_byte4_089)
# else
/* bindless textures */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 8c271c75e44..19c91248922 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -17,9 +17,9 @@
#ifndef __KERNEL_TYPES_H__
#define __KERNEL_TYPES_H__
-#include "kernel_math.h"
-#include "svm/svm_types.h"
-#include "util_static_assert.h"
+#include "kernel/kernel_math.h"
+#include "kernel/svm/svm_types.h"
+#include "util/util_static_assert.h"
#ifndef __KERNEL_GPU__
# define __KERNEL_CPU__
@@ -56,6 +56,8 @@ CCL_NAMESPACE_BEGIN
#define VOLUME_STACK_SIZE 16
+#define WORK_POOL_SIZE 64
+
/* device capabilities */
#ifdef __KERNEL_CPU__
# ifdef __KERNEL_SSE2__
@@ -63,27 +65,34 @@ CCL_NAMESPACE_BEGIN
# endif
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
-# define __BRANCHED_PATH__
+# ifndef __SPLIT_KERNEL__
+# define __BRANCHED_PATH__
+# endif
# ifdef WITH_OSL
# define __OSL__
# endif
# define __SUBSURFACE__
# define __CMJ__
# define __VOLUME__
-# define __VOLUME_DECOUPLED__
# define __VOLUME_SCATTER__
# define __SHADOW_RECORD_ALL__
-# define __VOLUME_RECORD_ALL__
+# ifndef __SPLIT_KERNEL__
+# define __VOLUME_DECOUPLED__
+# define __VOLUME_RECORD_ALL__
+# endif
#endif /* __KERNEL_CPU__ */
#ifdef __KERNEL_CUDA__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
-# define __BRANCHED_PATH__
# define __VOLUME__
# define __VOLUME_SCATTER__
# define __SUBSURFACE__
-# define __CMJ__
+# define __SHADOW_RECORD_ALL__
+# ifndef __SPLIT_KERNEL__
+# define __BRANCHED_PATH__
+# define __CMJ__
+# endif
#endif /* __KERNEL_CUDA__ */
#ifdef __KERNEL_OPENCL__
@@ -93,6 +102,10 @@ CCL_NAMESPACE_BEGIN
# ifdef __KERNEL_OPENCL_NVIDIA__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
+# define __SUBSURFACE__
+# define __VOLUME__
+# define __VOLUME_SCATTER__
+# define __SHADOW_RECORD_ALL__
# ifdef __KERNEL_EXPERIMENTAL__
# define __CMJ__
# endif
@@ -114,6 +127,10 @@ CCL_NAMESPACE_BEGIN
# define __CL_USE_NATIVE__
# define __KERNEL_SHADING__
# define __KERNEL_ADV_SHADING__
+# define __SUBSURFACE__
+# define __VOLUME__
+# define __VOLUME_SCATTER__
+# define __SHADOW_RECORD_ALL__
# endif /* __KERNEL_OPENCL_AMD__ */
# ifdef __KERNEL_OPENCL_INTEL_CPU__
@@ -140,6 +157,7 @@ CCL_NAMESPACE_BEGIN
#define __INTERSECTION_REFINE__
#define __CLAMP_SAMPLE__
#define __PATCH_EVAL__
+#define __SHADOW_TRICKS__
#ifdef __KERNEL_SHADING__
# define __SVM__
@@ -195,6 +213,9 @@ CCL_NAMESPACE_BEGIN
#ifdef __NO_TRANSPARENT__
# undef __TRANSPARENT_SHADOWS__
#endif
+#ifdef __NO_SHADOW_TRICKS__
+#undef __SHADOW_TRICKS__
+#endif
/* Random Numbers */
@@ -299,6 +320,8 @@ enum PathRayFlag {
PATH_RAY_MIS_SKIP = 4096,
PATH_RAY_DIFFUSE_ANCESTOR = 8192,
PATH_RAY_SINGLE_PASS_DONE = 16384,
+ PATH_RAY_SHADOW_CATCHER = 32768,
+ PATH_RAY_SHADOW_CATCHER_ONLY = 65536,
};
/* Closure Label */
@@ -428,6 +451,20 @@ typedef ccl_addr_space struct PathRadiance {
float4 shadow;
float mist;
#endif
+
+#ifdef __SHADOW_TRICKS__
+ /* Total light reachable across the path, ignoring shadow blocked queries. */
+ float3 path_total;
+ /* Total light reachable across the path with shadow blocked queries
+ * applied here.
+ *
+ * Dividing this figure by path_total will give estimate of shadow pass.
+ */
+ float3 path_total_shaded;
+
+ /* Color of the background on which shadow is alpha-overed. */
+ float3 shadow_color;
+#endif
} PathRadiance;
typedef struct BsdfEval {
@@ -443,6 +480,9 @@ typedef struct BsdfEval {
float3 subsurface;
float3 scatter;
#endif
+#ifdef __SHADOW_TRICKS__
+ float3 sum_no_mis;
+#endif
} BsdfEval;
/* Shader Flag */
@@ -536,7 +576,7 @@ typedef struct Ray {
/* Intersection */
-typedef ccl_addr_space struct Intersection {
+typedef struct Intersection {
float t, u, v;
int prim;
int object;
@@ -788,108 +828,89 @@ enum ShaderDataObjectFlag {
SD_OBJECT_INTERSECTS_VOLUME = (1 << 5),
/* Has position for motion vertices. */
SD_OBJECT_HAS_VERTEX_MOTION = (1 << 6),
+ /* object is used to catch shadows */
+ SD_OBJECT_SHADOW_CATCHER = (1 << 7),
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK |
SD_OBJECT_MOTION |
SD_OBJECT_TRANSFORM_APPLIED |
SD_OBJECT_NEGATIVE_SCALE_APPLIED |
SD_OBJECT_HAS_VOLUME |
- SD_OBJECT_INTERSECTS_VOLUME)
+ SD_OBJECT_INTERSECTS_VOLUME |
+ SD_OBJECT_SHADOW_CATCHER)
};
-#ifdef __SPLIT_KERNEL__
-# define SD_THREAD (get_global_id(1) * get_global_size(0) + get_global_id(0))
-# if !defined(__SPLIT_KERNEL_SOA__)
- /* ShaderData is stored as an Array-of-Structures */
-# define ccl_soa_member(type, name) type soa_##name
-# define ccl_fetch(s, t) (s[SD_THREAD].soa_##t)
-# define ccl_fetch_array(s, t, index) (&s[SD_THREAD].soa_##t[index])
-# else
- /* ShaderData is stored as an Structure-of-Arrays */
-# define SD_GLOBAL_SIZE (get_global_size(0) * get_global_size(1))
-# define SD_FIELD_SIZE(t) sizeof(((struct ShaderData*)0)->t)
-# define SD_OFFSETOF(t) ((char*)(&((struct ShaderData*)0)->t) - (char*)0)
-# define ccl_soa_member(type, name) type soa_##name
-# define ccl_fetch(s, t) (((ShaderData*)((ccl_addr_space char*)s + SD_GLOBAL_SIZE * SD_OFFSETOF(soa_##t) + SD_FIELD_SIZE(soa_##t) * SD_THREAD - SD_OFFSETOF(soa_##t)))->soa_##t)
-# define ccl_fetch_array(s, t, index) (&ccl_fetch(s, t)[index])
-# endif
-#else
-# define ccl_soa_member(type, name) type name
-# define ccl_fetch(s, t) (s->t)
-# define ccl_fetch_array(s, t, index) (&s->t[index])
-#endif
-
typedef ccl_addr_space struct ShaderData {
/* position */
- ccl_soa_member(float3, P);
+ float3 P;
/* smooth normal for shading */
- ccl_soa_member(float3, N);
+ float3 N;
/* true geometric normal */
- ccl_soa_member(float3, Ng);
+ float3 Ng;
/* view/incoming direction */
- ccl_soa_member(float3, I);
+ float3 I;
/* shader id */
- ccl_soa_member(int, shader);
+ int shader;
/* booleans describing shader, see ShaderDataFlag */
- ccl_soa_member(int, flag);
+ int flag;
/* booleans describing object of the shader, see ShaderDataObjectFlag */
- ccl_soa_member(int, object_flag);
+ int object_flag;
/* primitive id if there is one, ~0 otherwise */
- ccl_soa_member(int, prim);
+ int prim;
/* combined type and curve segment for hair */
- ccl_soa_member(int, type);
+ int type;
/* parametric coordinates
* - barycentric weights for triangles */
- ccl_soa_member(float, u);
- ccl_soa_member(float, v);
+ float u;
+ float v;
/* object id if there is one, ~0 otherwise */
- ccl_soa_member(int, object);
+ int object;
/* motion blur sample time */
- ccl_soa_member(float, time);
+ float time;
/* length of the ray being shaded */
- ccl_soa_member(float, ray_length);
+ float ray_length;
#ifdef __RAY_DIFFERENTIALS__
/* differential of P. these are orthogonal to Ng, not N */
- ccl_soa_member(differential3, dP);
+ differential3 dP;
/* differential of I */
- ccl_soa_member(differential3, dI);
+ differential3 dI;
/* differential of u, v */
- ccl_soa_member(differential, du);
- ccl_soa_member(differential, dv);
+ differential du;
+ differential dv;
#endif
#ifdef __DPDU__
/* differential of P w.r.t. parametric coordinates. note that dPdu is
* not readily suitable as a tangent for shading on triangles. */
- ccl_soa_member(float3, dPdu);
- ccl_soa_member(float3, dPdv);
+ float3 dPdu;
+ float3 dPdv;
#endif
#ifdef __OBJECT_MOTION__
/* object <-> world space transformations, cached to avoid
* re-interpolating them constantly for shading */
- ccl_soa_member(Transform, ob_tfm);
- ccl_soa_member(Transform, ob_itfm);
+ Transform ob_tfm;
+ Transform ob_itfm;
#endif
/* Closure data, we store a fixed array of closures */
- ccl_soa_member(struct ShaderClosure, closure[MAX_CLOSURE]);
- ccl_soa_member(int, num_closure);
- ccl_soa_member(int, num_closure_extra);
- ccl_soa_member(float, randb_closure);
- ccl_soa_member(float3, svm_closure_weight);
+ struct ShaderClosure closure[MAX_CLOSURE];
+ int num_closure;
+ int num_closure_extra;
+ float randb_closure;
+ float3 svm_closure_weight;
/* LCG state for closures that require additional random numbers. */
- ccl_soa_member(uint, lcg_state);
+ uint lcg_state;
/* ray start position, only set for backgrounds */
- ccl_soa_member(float3, ray_P);
- ccl_soa_member(differential3, ray_dP);
+ float3 ray_P;
+ differential3 ray_dP;
#ifdef __OSL__
struct KernelGlobals *osl_globals;
@@ -935,12 +956,16 @@ typedef struct PathState {
RNG rng_congruential;
VolumeStack volume_stack[VOLUME_STACK_SIZE];
#endif
+
+#ifdef __SHADOW_TRICKS__
+ int catcher_object;
+#endif
} PathState;
/* Subsurface */
/* Struct to gather multiple SSS hits. */
-struct SubsurfaceIntersection
+typedef struct SubsurfaceIntersection
{
Ray ray;
float3 weight[BSSRDF_MAX_HITS];
@@ -948,10 +973,10 @@ struct SubsurfaceIntersection
int num_hits;
struct Intersection hits[BSSRDF_MAX_HITS];
float3 Ng[BSSRDF_MAX_HITS];
-};
+} SubsurfaceIntersection;
/* Struct to gather SSS indirect rays and delay tracing them. */
-struct SubsurfaceIndirectRays
+typedef struct SubsurfaceIndirectRays
{
bool need_update_volume_stack;
bool tracing;
@@ -962,7 +987,7 @@ struct SubsurfaceIndirectRays
struct Ray rays[BSSRDF_MAX_HITS];
float3 throughputs[BSSRDF_MAX_HITS];
struct PathRadiance L[BSSRDF_MAX_HITS];
-};
+} SubsurfaceIndirectRays;
/* Constant Kernel Data
*
@@ -1201,7 +1226,8 @@ typedef struct KernelBVH {
int have_curves;
int have_instancing;
int use_qbvh;
- int pad1, pad2;
+ int use_bvh_steps;
+ int pad1;
} KernelBVH;
static_assert_align(KernelBVH, 16);
@@ -1296,20 +1322,19 @@ enum QueueNumber {
#define RAY_STATE_MASK 0x007
#define RAY_FLAG_MASK 0x0F8
enum RayState {
+ RAY_INVALID = 0,
/* Denotes ray is actively involved in path-iteration. */
- RAY_ACTIVE = 0,
+ RAY_ACTIVE,
/* Denotes ray has completed processing all samples and is inactive. */
- RAY_INACTIVE = 1,
+ RAY_INACTIVE,
/* Denoted ray has exited path-iteration and needs to update output buffer. */
- RAY_UPDATE_BUFFER = 2,
+ RAY_UPDATE_BUFFER,
/* Donotes ray has hit background */
- RAY_HIT_BACKGROUND = 3,
+ RAY_HIT_BACKGROUND,
/* Denotes ray has to be regenerated */
- RAY_TO_REGENERATE = 4,
+ RAY_TO_REGENERATE,
/* Denotes ray has been regenerated */
- RAY_REGENERATED = 5,
- /* Denotes ray should skip direct lighting */
- RAY_SKIP_DL = 6,
+ RAY_REGENERATED,
/* Flag's ray has to execute shadow blocked function in AO part */
RAY_SHADOW_RAY_CAST_AO = 16,
/* Flag's ray has to execute shadow blocked function in direct lighting part. */
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index c7cb29b5af2..9c0878249d4 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -38,7 +38,7 @@ typedef struct VolumeShaderCoefficients {
/* evaluate shader to get extinction coefficient at P */
ccl_device_inline bool volume_shader_extinction_sample(KernelGlobals *kg,
ShaderData *sd,
- PathState *state,
+ ccl_addr_space PathState *state,
float3 P,
float3 *extinction)
{
@@ -64,7 +64,7 @@ ccl_device_inline bool volume_shader_extinction_sample(KernelGlobals *kg,
/* evaluate shader to get absorption, scattering and emission at P */
ccl_device_inline bool volume_shader_sample(KernelGlobals *kg,
ShaderData *sd,
- PathState *state,
+ ccl_addr_space PathState *state,
float3 P,
VolumeShaderCoefficients *coeff)
{
@@ -112,7 +112,7 @@ ccl_device float kernel_volume_channel_get(float3 value, int channel)
return (channel == 0)? value.x: ((channel == 1)? value.y: value.z);
}
-ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, VolumeStack *stack)
+ccl_device bool volume_stack_is_heterogeneous(KernelGlobals *kg, ccl_addr_space VolumeStack *stack)
{
for(int i = 0; stack[i].shader != SHADER_NONE; i++) {
int shader_flag = kernel_tex_fetch(__shader_flag, (stack[i].shader & SHADER_MASK)*SHADER_SIZE);
@@ -161,7 +161,11 @@ ccl_device int volume_stack_sampling_method(KernelGlobals *kg, VolumeStack *stac
/* homogeneous volume: assume shader evaluation at the starts gives
* the extinction coefficient for the entire line segment */
-ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd, float3 *throughput)
+ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ float3 *throughput)
{
float3 sigma_t;
@@ -171,7 +175,11 @@ ccl_device void kernel_volume_shadow_homogeneous(KernelGlobals *kg, PathState *s
/* heterogeneous volume: integrate stepping through the volume until we
* reach the end, get absorbed entirely, or run out of iterations */
-ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState *state, Ray *ray, ShaderData *sd, float3 *throughput)
+ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ float3 *throughput)
{
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
@@ -179,7 +187,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* prepare for stepping */
int max_steps = kernel_data.integrator.volume_max_steps;
float step = kernel_data.integrator.volume_step_size;
- float random_jitter_offset = lcg_step_float(&state->rng_congruential) * step;
+ float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step;
/* compute extinction at the start */
float t = 0.0f;
@@ -193,7 +201,7 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* use random position inside this segment to sample shader */
if(new_t == ray->t)
- random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt;
+ random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * dt;
float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
float3 sigma_t;
@@ -227,7 +235,11 @@ ccl_device void kernel_volume_shadow_heterogeneous(KernelGlobals *kg, PathState
/* get the volume attenuation over line segment defined by ray, with the
* assumption that there are no surfaces blocking light between the endpoints */
-ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg, ShaderData *shadow_sd, PathState *state, Ray *ray, float3 *throughput)
+ccl_device_noinline void kernel_volume_shadow(KernelGlobals *kg,
+ ShaderData *shadow_sd,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ float3 *throughput)
{
shader_setup_from_volume(kg, shadow_sd, ray);
@@ -341,9 +353,15 @@ ccl_device float3 kernel_volume_emission_integrate(VolumeShaderCoefficients *coe
/* homogeneous volume: assume shader evaluation at the start gives
* the volume shading coefficient for the entire line segment */
-ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGlobals *kg,
- PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput,
- RNG *rng, bool probalistic_scatter)
+ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
+ KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput,
+ RNG *rng,
+ bool probalistic_scatter)
{
VolumeShaderCoefficients coeff;
@@ -444,8 +462,14 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(KernelGloba
* volume until we reach the end, get absorbed entirely, or run out of
* iterations. this does probabilistically scatter or get transmitted through
* for path tracing where we don't want to branch. */
-ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(KernelGlobals *kg,
- PathState *state, Ray *ray, ShaderData *sd, PathRadiance *L, float3 *throughput, RNG *rng)
+ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
+ KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ Ray *ray,
+ ShaderData *sd,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput,
+ RNG *rng)
{
float3 tp = *throughput;
const float tp_eps = 1e-6f; /* todo: this is likely not the right value */
@@ -453,7 +477,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
/* prepare for stepping */
int max_steps = kernel_data.integrator.volume_max_steps;
float step_size = kernel_data.integrator.volume_step_size;
- float random_jitter_offset = lcg_step_float(&state->rng_congruential) * step_size;
+ float random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * step_size;
/* compute coefficients at the start */
float t = 0.0f;
@@ -474,7 +498,7 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
/* use random position inside this segment to sample shader */
if(new_t == ray->t)
- random_jitter_offset = lcg_step_float(&state->rng_congruential) * dt;
+ random_jitter_offset = lcg_step_float_addrspace(&state->rng_congruential) * dt;
float3 new_P = ray->P + ray->D * (t + random_jitter_offset);
VolumeShaderCoefficients coeff;
@@ -579,8 +603,15 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
* ray, with the assumption that there are no surfaces blocking light
* between the endpoints. distance sampling is used to decide if we will
* scatter or not. */
-ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals *kg,
- PathState *state, ShaderData *sd, Ray *ray, PathRadiance *L, float3 *throughput, RNG *rng, bool heterogeneous)
+ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(
+ KernelGlobals *kg,
+ ccl_addr_space PathState *state,
+ ShaderData *sd,
+ Ray *ray,
+ PathRadiance *L,
+ ccl_addr_space float3 *throughput,
+ RNG *rng,
+ bool heterogeneous)
{
shader_setup_from_volume(kg, sd, ray);
@@ -590,6 +621,7 @@ ccl_device_noinline VolumeIntegrateResult kernel_volume_integrate(KernelGlobals
return kernel_volume_integrate_homogeneous(kg, state, ray, sd, L, throughput, rng, true);
}
+#ifndef __SPLIT_KERNEL__
/* Decoupled Volume Sampling
*
* VolumeSegment is list of coefficients and transmittance stored at all steps
@@ -966,7 +998,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
mis_weight = 2.0f*power_heuristic(pdf, distance_pdf);
}
}
- if(sample_t < 1e-6f) {
+ if(sample_t < 1e-6f || pdf == 0.0f) {
return VOLUME_PATH_SCATTERED;
}
@@ -990,6 +1022,7 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
return VOLUME_PATH_SCATTERED;
}
+#endif /* __SPLIT_KERNEL */
/* decide if we need to use decoupled or not */
ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneous, bool direct, int sampling_method)
@@ -1021,9 +1054,9 @@ ccl_device bool kernel_volume_use_decoupled(KernelGlobals *kg, bool heterogeneou
ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
ShaderData *stack_sd,
- const PathState *state,
- const Ray *ray,
- VolumeStack *stack)
+ ccl_addr_space const PathState *state,
+ ccl_addr_space const Ray *ray,
+ ccl_addr_space VolumeStack *stack)
{
/* NULL ray happens in the baker, does it need proper initialization of
* camera in volume?
@@ -1166,7 +1199,7 @@ ccl_device void kernel_volume_stack_init(KernelGlobals *kg,
}
}
-ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack)
+ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd, ccl_addr_space VolumeStack *stack)
{
/* todo: we should have some way for objects to indicate if they want the
* world shader to work inside them. excluding it by default is problematic
@@ -1215,7 +1248,7 @@ ccl_device void kernel_volume_stack_enter_exit(KernelGlobals *kg, ShaderData *sd
ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
ShaderData *stack_sd,
Ray *ray,
- VolumeStack *stack)
+ ccl_addr_space VolumeStack *stack)
{
kernel_assert(kernel_data.integrator.use_volumes);
@@ -1277,7 +1310,7 @@ ccl_device void kernel_volume_stack_update_for_subsurface(KernelGlobals *kg,
* the world's one after the last bounce to avoid render artifacts.
*/
ccl_device_inline void kernel_volume_clean_stack(KernelGlobals *kg,
- VolumeStack *volume_stack)
+ ccl_addr_space VolumeStack *volume_stack)
{
if(kernel_data.background.volume_shader != SHADER_NONE) {
/* Keep the world's volume in stack. */
diff --git a/intern/cycles/kernel/kernel_work_stealing.h b/intern/cycles/kernel/kernel_work_stealing.h
index 7d559b1aa31..28fc5ce1c30 100644
--- a/intern/cycles/kernel/kernel_work_stealing.h
+++ b/intern/cycles/kernel/kernel_work_stealing.h
@@ -17,177 +17,102 @@
#ifndef __KERNEL_WORK_STEALING_H__
#define __KERNEL_WORK_STEALING_H__
+CCL_NAMESPACE_BEGIN
+
/*
* Utility functions for work stealing
*/
-#ifdef __WORK_STEALING__
-
#ifdef __KERNEL_OPENCL__
# pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
#endif
-uint get_group_id_with_ray_index(uint ray_index,
- uint tile_dim_x,
- uint tile_dim_y,
- uint parallel_samples,
- int dim)
+ccl_device_inline uint kernel_total_work_size(KernelGlobals *kg)
+{
+ return kernel_split_params.w * kernel_split_params.h * kernel_split_params.num_samples;
+}
+
+ccl_device_inline uint kernel_num_work_pools(KernelGlobals *kg)
+{
+ return ccl_global_size(0) * ccl_global_size(1) / WORK_POOL_SIZE;
+}
+
+ccl_device_inline uint work_pool_from_ray_index(KernelGlobals *kg, uint ray_index)
+{
+ return ray_index / WORK_POOL_SIZE;
+}
+
+ccl_device_inline uint work_pool_work_size(KernelGlobals *kg, uint work_pool)
{
- if(dim == 0) {
- uint x_span = ray_index % (tile_dim_x * parallel_samples);
- return x_span / get_local_size(0);
+ uint total_work_size = kernel_total_work_size(kg);
+ uint num_pools = kernel_num_work_pools(kg);
+
+ if(work_pool >= num_pools || work_pool * WORK_POOL_SIZE >= total_work_size) {
+ return 0;
+ }
+
+ uint work_size = (total_work_size / (num_pools * WORK_POOL_SIZE)) * WORK_POOL_SIZE;
+
+ uint remainder = (total_work_size % (num_pools * WORK_POOL_SIZE));
+ if(work_pool < remainder / WORK_POOL_SIZE) {
+ work_size += WORK_POOL_SIZE;
}
- else /*if(dim == 1)*/ {
- kernel_assert(dim == 1);
- uint y_span = ray_index / (tile_dim_x * parallel_samples);
- return y_span / get_local_size(1);
+ else if(work_pool == remainder / WORK_POOL_SIZE) {
+ work_size += remainder % WORK_POOL_SIZE;
}
+
+ return work_size;
}
-uint get_total_work(uint tile_dim_x,
- uint tile_dim_y,
- uint grp_idx,
- uint grp_idy,
- uint num_samples)
+ccl_device_inline uint get_global_work_index(KernelGlobals *kg, uint work_index, uint ray_index)
{
- uint threads_within_tile_border_x =
- (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
- : get_local_size(0);
- uint threads_within_tile_border_y =
- (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
- : get_local_size(1);
-
- threads_within_tile_border_x =
- (threads_within_tile_border_x == 0) ? get_local_size(0)
- : threads_within_tile_border_x;
- threads_within_tile_border_y =
- (threads_within_tile_border_y == 0) ? get_local_size(1)
- : threads_within_tile_border_y;
-
- return threads_within_tile_border_x *
- threads_within_tile_border_y *
- num_samples;
+ uint num_pools = kernel_num_work_pools(kg);
+ uint pool = work_pool_from_ray_index(kg, ray_index);
+
+ return (work_index / WORK_POOL_SIZE) * (num_pools * WORK_POOL_SIZE)
+ + (pool * WORK_POOL_SIZE)
+ + (work_index % WORK_POOL_SIZE);
}
-/* Returns 0 in case there is no next work available */
-/* Returns 1 in case work assigned is valid */
-int get_next_work(ccl_global uint *work_pool,
- ccl_private uint *my_work,
- uint tile_dim_x,
- uint tile_dim_y,
- uint num_samples,
- uint parallel_samples,
- uint ray_index)
+/* Returns true if there is work */
+ccl_device bool get_next_work(KernelGlobals *kg, ccl_private uint *work_index, uint ray_index)
{
- uint grp_idx = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 0);
- uint grp_idy = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 1);
- uint total_work = get_total_work(tile_dim_x,
- tile_dim_y,
- grp_idx,
- grp_idy,
- num_samples);
- uint group_index = grp_idy * get_num_groups(0) + grp_idx;
- *my_work = atomic_inc(&work_pool[group_index]);
- return (*my_work < total_work) ? 1 : 0;
+ uint work_pool = work_pool_from_ray_index(kg, ray_index);
+ uint pool_size = work_pool_work_size(kg, work_pool);
+
+ if(pool_size == 0) {
+ return false;
+ }
+
+ *work_index = atomic_fetch_and_inc_uint32(&kernel_split_params.work_pools[work_pool]);
+ return (*work_index < pool_size);
}
-/* This function assumes that the passed my_work is valid. */
-/* Decode sample number w.r.t. assigned my_work. */
-uint get_my_sample(uint my_work,
- uint tile_dim_x,
- uint tile_dim_y,
- uint parallel_samples,
- uint ray_index)
+/* This function assumes that the passed `work` is valid. */
+/* Decode sample number w.r.t. assigned `work`. */
+ccl_device uint get_work_sample(KernelGlobals *kg, uint work_index, uint ray_index)
{
- uint grp_idx = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 0);
- uint grp_idy = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 1);
- uint threads_within_tile_border_x =
- (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
- : get_local_size(0);
- uint threads_within_tile_border_y =
- (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
- : get_local_size(1);
-
- threads_within_tile_border_x =
- (threads_within_tile_border_x == 0) ? get_local_size(0)
- : threads_within_tile_border_x;
- threads_within_tile_border_y =
- (threads_within_tile_border_y == 0) ? get_local_size(1)
- : threads_within_tile_border_y;
-
- return my_work /
- (threads_within_tile_border_x * threads_within_tile_border_y);
+ return get_global_work_index(kg, work_index, ray_index) / (kernel_split_params.w * kernel_split_params.h);
}
-/* Decode pixel and tile position w.r.t. assigned my_work. */
-void get_pixel_tile_position(ccl_private uint *pixel_x,
+/* Decode pixel and tile position w.r.t. assigned `work`. */
+ccl_device void get_work_pixel_tile_position(KernelGlobals *kg,
+ ccl_private uint *pixel_x,
ccl_private uint *pixel_y,
ccl_private uint *tile_x,
ccl_private uint *tile_y,
- uint my_work,
- uint tile_dim_x,
- uint tile_dim_y,
- uint tile_offset_x,
- uint tile_offset_y,
- uint parallel_samples,
+ uint work_index,
uint ray_index)
{
- uint grp_idx = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 0);
- uint grp_idy = get_group_id_with_ray_index(ray_index,
- tile_dim_x,
- tile_dim_y,
- parallel_samples,
- 1);
- uint threads_within_tile_border_x =
- (grp_idx == (get_num_groups(0) - 1)) ? tile_dim_x % get_local_size(0)
- : get_local_size(0);
- uint threads_within_tile_border_y =
- (grp_idy == (get_num_groups(1) - 1)) ? tile_dim_y % get_local_size(1)
- : get_local_size(1);
-
- threads_within_tile_border_x =
- (threads_within_tile_border_x == 0) ? get_local_size(0)
- : threads_within_tile_border_x;
- threads_within_tile_border_y =
- (threads_within_tile_border_y == 0) ? get_local_size(1)
- : threads_within_tile_border_y;
-
- uint total_associated_pixels =
- threads_within_tile_border_x * threads_within_tile_border_y;
- uint work_group_pixel_index = my_work % total_associated_pixels;
- uint work_group_pixel_x =
- work_group_pixel_index % threads_within_tile_border_x;
- uint work_group_pixel_y =
- work_group_pixel_index / threads_within_tile_border_x;
-
- *pixel_x =
- tile_offset_x + (grp_idx * get_local_size(0)) + work_group_pixel_x;
- *pixel_y =
- tile_offset_y + (grp_idy * get_local_size(1)) + work_group_pixel_y;
- *tile_x = *pixel_x - tile_offset_x;
- *tile_y = *pixel_y - tile_offset_y;
+ uint pixel_index = get_global_work_index(kg, work_index, ray_index) % (kernel_split_params.w*kernel_split_params.h);
+
+ *tile_x = pixel_index % kernel_split_params.w;
+ *tile_y = pixel_index / kernel_split_params.w;
+
+ *pixel_x = *tile_x + kernel_split_params.x;
+ *pixel_y = *tile_y + kernel_split_params.y;
}
-#endif /* __WORK_STEALING__ */
+CCL_NAMESPACE_END
#endif /* __KERNEL_WORK_STEALING_H__ */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index 72dbbd9a416..16992c681e6 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -56,9 +56,9 @@
/* do nothing */
#endif
-#include "kernel.h"
+#include "kernel/kernel.h"
#define KERNEL_ARCH cpu
-#include "kernel_cpu_impl.h"
+#include "kernel/kernels/cpu/kernel_cpu_impl.h"
CCL_NAMESPACE_BEGIN
@@ -90,7 +90,7 @@ void kernel_tex_copy(KernelGlobals *kg,
kg->tname.width = width; \
}
#define KERNEL_IMAGE_TEX(type, ttype, tname)
-#include "kernel_textures.h"
+#include "kernel/kernel_textures.h"
else if(strstr(name, "__tex_image_float4")) {
texture_image_float4 *tex = NULL;
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
index 1350d9e5c2e..2600d977972 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx.cpp
@@ -28,10 +28,10 @@
# define __KERNEL_AVX__
#endif
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
-# include "kernel.h"
+# include "kernel/kernel.h"
# define KERNEL_ARCH cpu_avx
-# include "kernel_cpu_impl.h"
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
index 1a416e771ee..dba15d037ac 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_avx2.cpp
@@ -29,10 +29,10 @@
# define __KERNEL_AVX2__
#endif
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
-# include "kernel.h"
+# include "kernel/kernel.h"
# define KERNEL_ARCH cpu_avx2
-# include "kernel_cpu_impl.h"
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
index 1a07c705f1c..896b80d783e 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h
@@ -49,4 +49,44 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
int offset,
int sample);
+/* Split kernels */
+
+void KERNEL_FUNCTION_FULL_NAME(data_init)(
+ KernelGlobals *kg,
+ ccl_constant KernelData *data,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
+ ccl_global uint *rng_state,
+ int start_sample,
+ int end_sample,
+ int sx, int sy, int sw, int sh, int offset, int stride,
+ ccl_global int *Queue_index,
+ int queuesize,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+ ccl_global float *buffer);
+
+#define DECLARE_SPLIT_KERNEL_FUNCTION(name) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData *data);
+
+DECLARE_SPLIT_KERNEL_FUNCTION(path_init)
+DECLARE_SPLIT_KERNEL_FUNCTION(scene_intersect)
+DECLARE_SPLIT_KERNEL_FUNCTION(lamp_emission)
+DECLARE_SPLIT_KERNEL_FUNCTION(do_volume)
+DECLARE_SPLIT_KERNEL_FUNCTION(queue_enqueue)
+DECLARE_SPLIT_KERNEL_FUNCTION(indirect_background)
+DECLARE_SPLIT_KERNEL_FUNCTION(shader_eval)
+DECLARE_SPLIT_KERNEL_FUNCTION(holdout_emission_blurring_pathtermination_ao)
+DECLARE_SPLIT_KERNEL_FUNCTION(subsurface_scatter)
+DECLARE_SPLIT_KERNEL_FUNCTION(direct_lighting)
+DECLARE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
+DECLARE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DECLARE_SPLIT_KERNEL_FUNCTION(next_iteration_setup)
+DECLARE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
+DECLARE_SPLIT_KERNEL_FUNCTION(buffer_update)
+
+void KERNEL_FUNCTION_FULL_NAME(register_functions)(void(*reg)(const char* name, void* func));
+
#undef KERNEL_ARCH
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
index ec82d4b4c22..148b2eef568 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h
@@ -20,18 +20,45 @@
* simply includes this file without worry of copying actual implementation over.
*/
-#include "kernel_compat_cpu.h"
-#include "kernel_math.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
-#include "kernel_cpu_image.h"
-#include "kernel_film.h"
-#include "kernel_path.h"
-#include "kernel_path_branched.h"
-#include "kernel_bake.h"
+#include "kernel/kernel_compat_cpu.h"
+
+#ifndef __SPLIT_KERNEL__
+# include "kernel/kernel_math.h"
+# include "kernel/kernel_types.h"
+
+# include "kernel/split/kernel_split_data.h"
+# include "kernel/kernel_globals.h"
+
+# include "kernel/kernels/cpu/kernel_cpu_image.h"
+# include "kernel/kernel_film.h"
+# include "kernel/kernel_path.h"
+# include "kernel/kernel_path_branched.h"
+# include "kernel/kernel_bake.h"
+#else
+# include "kernel/split/kernel_split_common.h"
+
+# include "kernel/split/kernel_data_init.h"
+# include "kernel/split/kernel_path_init.h"
+# include "kernel/split/kernel_scene_intersect.h"
+# include "kernel/split/kernel_lamp_emission.h"
+# include "kernel/split/kernel_do_volume.h"
+# include "kernel/split/kernel_queue_enqueue.h"
+# include "kernel/split/kernel_indirect_background.h"
+# include "kernel/split/kernel_shader_eval.h"
+# include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
+# include "kernel/split/kernel_subsurface_scatter.h"
+# include "kernel/split/kernel_direct_lighting.h"
+# include "kernel/split/kernel_shadow_blocked_ao.h"
+# include "kernel/split/kernel_shadow_blocked_dl.h"
+# include "kernel/split/kernel_next_iteration_setup.h"
+# include "kernel/split/kernel_indirect_subsurface.h"
+# include "kernel/split/kernel_buffer_update.h"
+#endif
CCL_NAMESPACE_BEGIN
+#ifndef __SPLIT_KERNEL__
+
/* Path Tracing */
void KERNEL_FUNCTION_FULL_NAME(path_trace)(KernelGlobals *kg,
@@ -131,4 +158,72 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg,
}
}
+#else /* __SPLIT_KERNEL__ */
+
+/* Split Kernel Path Tracing */
+
+#define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
+ { \
+ kernel_##name(kg); \
+ }
+
+#define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
+ void KERNEL_FUNCTION_FULL_NAME(name)(KernelGlobals *kg, KernelData* /*data*/) \
+ { \
+ ccl_local type locals; \
+ kernel_##name(kg, &locals); \
+ }
+
+DEFINE_SPLIT_KERNEL_FUNCTION(path_init)
+DEFINE_SPLIT_KERNEL_FUNCTION(scene_intersect)
+DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission)
+DEFINE_SPLIT_KERNEL_FUNCTION(do_volume)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals)
+DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
+DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
+
+void KERNEL_FUNCTION_FULL_NAME(register_functions)(void(*reg)(const char* name, void* func))
+{
+#define REGISTER_NAME_STRING(name) #name
+#define REGISTER_EVAL_NAME(name) REGISTER_NAME_STRING(name)
+#define REGISTER(name) reg(REGISTER_EVAL_NAME(KERNEL_FUNCTION_FULL_NAME(name)), (void*)KERNEL_FUNCTION_FULL_NAME(name));
+
+ REGISTER(path_trace);
+ REGISTER(convert_to_byte);
+ REGISTER(convert_to_half_float);
+ REGISTER(shader);
+
+ REGISTER(data_init);
+ REGISTER(path_init);
+ REGISTER(scene_intersect);
+ REGISTER(lamp_emission);
+ REGISTER(do_volume);
+ REGISTER(queue_enqueue);
+ REGISTER(indirect_background);
+ REGISTER(shader_eval);
+ REGISTER(holdout_emission_blurring_pathtermination_ao);
+ REGISTER(subsurface_scatter);
+ REGISTER(direct_lighting);
+ REGISTER(shadow_blocked_ao);
+ REGISTER(shadow_blocked_dl);
+ REGISTER(next_iteration_setup);
+ REGISTER(indirect_subsurface);
+ REGISTER(buffer_update);
+
+#undef REGISTER
+#undef REGISTER_EVAL_NAME
+#undef REGISTER_NAME_STRING
+}
+
+#endif /* __SPLIT_KERNEL__ */
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split.cpp
new file mode 100644
index 00000000000..ca750e5a00d
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* CPU kernel entry points */
+
+/* On x86-64, we can assume SSE2, so avoid the extra kernel and compile this
+ * one with SSE2 intrinsics.
+ */
+#if defined(__x86_64__) || defined(_M_X64)
+# define __KERNEL_SSE2__
+#endif
+
+#define __SPLIT_KERNEL__
+
+/* When building kernel for native machine detect kernel features from the flags
+ * set by compiler.
+ */
+#ifdef WITH_KERNEL_NATIVE
+# ifdef __SSE2__
+# ifndef __KERNEL_SSE2__
+# define __KERNEL_SSE2__
+# endif
+# endif
+# ifdef __SSE3__
+# define __KERNEL_SSE3__
+# endif
+# ifdef __SSSE3__
+# define __KERNEL_SSSE3__
+# endif
+# ifdef __SSE4_1__
+# define __KERNEL_SSE41__
+# endif
+# ifdef __AVX__
+# define __KERNEL_AVX__
+# endif
+# ifdef __AVX2__
+# define __KERNEL_SSE__
+# define __KERNEL_AVX2__
+# endif
+#endif
+
+/* quiet unused define warnings */
+#if defined(__KERNEL_SSE2__)
+ /* do nothing */
+#endif
+
+#include "kernel/kernel.h"
+#define KERNEL_ARCH cpu
+#include "kernel/kernels/cpu/kernel_cpu_impl.h"
+
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp
new file mode 100644
index 00000000000..27a746a0799
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_avx.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with AVX
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE2__
+# define __KERNEL_SSE3__
+# define __KERNEL_SSSE3__
+# define __KERNEL_SSE41__
+# define __KERNEL_AVX__
+#endif
+
+#define __SPLIT_KERNEL__
+
+#include "util/util_optimization.h"
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX
+# include "kernel/kernel.h"
+# define KERNEL_ARCH cpu_avx
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp
new file mode 100644
index 00000000000..364d279a189
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_avx2.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011-2014 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with AVX2
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE__
+# define __KERNEL_SSE2__
+# define __KERNEL_SSE3__
+# define __KERNEL_SSSE3__
+# define __KERNEL_SSE41__
+# define __KERNEL_AVX__
+# define __KERNEL_AVX2__
+#endif
+
+#define __SPLIT_KERNEL__
+
+#include "util/util_optimization.h"
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2
+# include "kernel/kernel.h"
+# define KERNEL_ARCH cpu_avx2
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp
new file mode 100644
index 00000000000..0afb481296f
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse2.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE2
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE2__
+#endif
+
+#define __SPLIT_KERNEL__
+
+#include "util/util_optimization.h"
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
+# include "kernel/kernel.h"
+# define KERNEL_ARCH cpu_sse2
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp
new file mode 100644
index 00000000000..13d00813591
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse3.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE2__
+# define __KERNEL_SSE3__
+# define __KERNEL_SSSE3__
+#endif
+
+#define __SPLIT_KERNEL__
+
+#include "util/util_optimization.h"
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
+# include "kernel/kernel.h"
+# define KERNEL_ARCH cpu_sse3
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp b/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp
new file mode 100644
index 00000000000..a4312071edc
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cpu/kernel_split_sse41.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* Optimized CPU kernel entry points. This file is compiled with SSE3/SSSE3
+ * optimization flags and nearly all functions inlined, while kernel.cpp
+ * is compiled without for other CPU's. */
+
+/* SSE optimization disabled for now on 32 bit, see bug #36316 */
+#if !(defined(__GNUC__) && (defined(i386) || defined(_M_IX86)))
+# define __KERNEL_SSE2__
+# define __KERNEL_SSE3__
+# define __KERNEL_SSSE3__
+# define __KERNEL_SSE41__
+#endif
+
+#define __SPLIT_KERNEL__
+
+#include "util/util_optimization.h"
+
+#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
+# include "kernel/kernel.h"
+# define KERNEL_ARCH cpu_sse41
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
+#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
index a5f2d6e7294..1acfaa91ac9 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse2.cpp
@@ -23,10 +23,10 @@
# define __KERNEL_SSE2__
#endif
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE2
-# include "kernel.h"
+# include "kernel/kernel.h"
# define KERNEL_ARCH cpu_sse2
-# include "kernel_cpu_impl.h"
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE2 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
index 86f9ce991f8..f7b6a2e21fe 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse3.cpp
@@ -25,10 +25,10 @@
# define __KERNEL_SSSE3__
#endif
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE3
-# include "kernel.h"
+# include "kernel/kernel.h"
# define KERNEL_ARCH cpu_sse3
-# include "kernel_cpu_impl.h"
+# include "kernel/kernels/cpu/kernel_cpu_impl.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE3 */
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
index c174406047d..1900c6e3012 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel_sse41.cpp
@@ -26,10 +26,10 @@
# define __KERNEL_SSE41__
#endif
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#ifdef WITH_CYCLES_OPTIMIZED_KERNEL_SSE41
-# include "kernel.h"
+# include "kernel/kernel.h"
# define KERNEL_ARCH cpu_sse41
-# include "kernel_cpu_impl.h"
+# include "kernel/kernels/cpu//kernel_cpu_impl.h"
#endif /* WITH_CYCLES_OPTIMIZED_KERNEL_SSE41 */
diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu
index eb2b6ea5414..dc343cb387a 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel.cu
+++ b/intern/cycles/kernel/kernels/cuda/kernel.cu
@@ -16,113 +16,19 @@
/* CUDA kernel entry points */
-#include "../../kernel_compat_cuda.h"
-#include "../../kernel_math.h"
-#include "../../kernel_types.h"
-#include "../../kernel_globals.h"
-#include "../../kernel_film.h"
-#include "../../kernel_path.h"
-#include "../../kernel_path_branched.h"
-#include "../../kernel_bake.h"
-
-/* device data taken from CUDA occupancy calculator */
-
#ifdef __CUDA_ARCH__
-/* 2.0 and 2.1 */
-#if __CUDA_ARCH__ == 200 || __CUDA_ARCH__ == 210
-# define CUDA_MULTIPRESSOR_MAX_REGISTERS 32768
-# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 8
-# define CUDA_BLOCK_MAX_THREADS 1024
-# define CUDA_THREAD_MAX_REGISTERS 63
-
-/* tunable parameters */
-# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 32
-# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 40
-
-/* 3.0 and 3.5 */
-#elif __CUDA_ARCH__ == 300 || __CUDA_ARCH__ == 350
-# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
-# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
-# define CUDA_BLOCK_MAX_THREADS 1024
-# define CUDA_THREAD_MAX_REGISTERS 63
-
-/* tunable parameters */
-# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 63
-# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-
-/* 3.2 */
-#elif __CUDA_ARCH__ == 320
-# define CUDA_MULTIPRESSOR_MAX_REGISTERS 32768
-# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
-# define CUDA_BLOCK_MAX_THREADS 1024
-# define CUDA_THREAD_MAX_REGISTERS 63
-
-/* tunable parameters */
-# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 63
-# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-
-/* 3.7 */
-#elif __CUDA_ARCH__ == 370
-# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
-# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
-# define CUDA_BLOCK_MAX_THREADS 1024
-# define CUDA_THREAD_MAX_REGISTERS 255
-
-/* tunable parameters */
-# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 63
-# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-
-/* 5.0, 5.2, 5.3, 6.0, 6.1 */
-#elif __CUDA_ARCH__ >= 500
-# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
-# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 32
-# define CUDA_BLOCK_MAX_THREADS 1024
-# define CUDA_THREAD_MAX_REGISTERS 255
-
-/* tunable parameters */
-# define CUDA_THREADS_BLOCK_WIDTH 16
-# define CUDA_KERNEL_MAX_REGISTERS 48
-# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
-
-/* unknown architecture */
-#else
-# error "Unknown or unsupported CUDA architecture, can't determine launch bounds"
-#endif
-
-/* compute number of threads per block and minimum blocks per multiprocessor
- * given the maximum number of registers per thread */
-
-#define CUDA_LAUNCH_BOUNDS(threads_block_width, thread_num_registers) \
- __launch_bounds__( \
- threads_block_width*threads_block_width, \
- CUDA_MULTIPRESSOR_MAX_REGISTERS/(threads_block_width*threads_block_width*thread_num_registers) \
- )
-
-/* sanity checks */
-
-#if CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH > CUDA_BLOCK_MAX_THREADS
-# error "Maximum number of threads per block exceeded"
-#endif
-
-#if CUDA_MULTIPRESSOR_MAX_REGISTERS/(CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH*CUDA_KERNEL_MAX_REGISTERS) > CUDA_MULTIPROCESSOR_MAX_BLOCKS
-# error "Maximum number of blocks per multiprocessor exceeded"
-#endif
-
-#if CUDA_KERNEL_MAX_REGISTERS > CUDA_THREAD_MAX_REGISTERS
-# error "Maximum number of registers per thread exceeded"
-#endif
-
-#if CUDA_KERNEL_BRANCHED_MAX_REGISTERS > CUDA_THREAD_MAX_REGISTERS
-# error "Maximum number of registers per thread exceeded"
-#endif
+#include "kernel/kernel_compat_cuda.h"
+#include "kernel_config.h"
+#include "kernel/kernel_math.h"
+#include "kernel/kernel_types.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_film.h"
+#include "kernel/kernel_path.h"
+#include "kernel/kernel_path_branched.h"
+#include "kernel/kernel_bake.h"
/* kernels */
-
extern "C" __global__ void
CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
kernel_cuda_path_trace(float *buffer, uint *rng_state, int sample, int sx, int sy, int sw, int sh, int offset, int stride)
@@ -130,8 +36,10 @@ kernel_cuda_path_trace(float *buffer, uint *rng_state, int sample, int sx, int s
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
- kernel_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride);
+ if(x < sx + sw && y < sy + sh) {
+ KernelGlobals kg;
+ kernel_path_trace(&kg, buffer, rng_state, sample, x, y, offset, stride);
+ }
}
#ifdef __BRANCHED_PATH__
@@ -142,8 +50,10 @@ kernel_cuda_branched_path_trace(float *buffer, uint *rng_state, int sample, int
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
- kernel_branched_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride);
+ if(x < sx + sw && y < sy + sh) {
+ KernelGlobals kg;
+ kernel_branched_path_trace(&kg, buffer, rng_state, sample, x, y, offset, stride);
+ }
}
#endif
@@ -154,8 +64,9 @@ kernel_cuda_convert_to_byte(uchar4 *rgba, float *buffer, float sample_scale, int
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
+ if(x < sx + sw && y < sy + sh) {
kernel_film_convert_to_byte(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+ }
}
extern "C" __global__ void
@@ -165,8 +76,9 @@ kernel_cuda_convert_to_half_float(uchar4 *rgba, float *buffer, float sample_scal
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
- if(x < sx + sw && y < sy + sh)
+ if(x < sx + sw && y < sy + sh) {
kernel_film_convert_to_half_float(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+ }
}
extern "C" __global__ void
@@ -183,7 +95,8 @@ kernel_cuda_shader(uint4 *input,
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
if(x < sx + sw) {
- kernel_shader_evaluate(NULL,
+ KernelGlobals kg;
+ kernel_shader_evaluate(&kg,
input,
output,
output_luma,
@@ -200,8 +113,10 @@ kernel_cuda_bake(uint4 *input, float4 *output, int type, int filter, int sx, int
{
int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
- if(x < sx + sw)
- kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, filter, x, offset, sample);
+ if(x < sx + sw) {
+ KernelGlobals kg;
+ kernel_bake_evaluate(&kg, input, output, (ShaderEvalType)type, filter, x, offset, sample);
+ }
}
#endif
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_config.h b/intern/cycles/kernel/kernels/cuda/kernel_config.h
new file mode 100644
index 00000000000..9fa39dc9ebb
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cuda/kernel_config.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011-2013 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.
+ */
+
+/* device data taken from CUDA occupancy calculator */
+
+/* 2.0 and 2.1 */
+#if __CUDA_ARCH__ == 200 || __CUDA_ARCH__ == 210
+# define CUDA_MULTIPRESSOR_MAX_REGISTERS 32768
+# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 8
+# define CUDA_BLOCK_MAX_THREADS 1024
+# define CUDA_THREAD_MAX_REGISTERS 63
+
+/* tunable parameters */
+# define CUDA_THREADS_BLOCK_WIDTH 16
+# define CUDA_KERNEL_MAX_REGISTERS 32
+# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 40
+
+/* 3.0 and 3.5 */
+#elif __CUDA_ARCH__ == 300 || __CUDA_ARCH__ == 350
+# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
+# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
+# define CUDA_BLOCK_MAX_THREADS 1024
+# define CUDA_THREAD_MAX_REGISTERS 63
+
+/* tunable parameters */
+# define CUDA_THREADS_BLOCK_WIDTH 16
+# define CUDA_KERNEL_MAX_REGISTERS 63
+# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
+/* 3.2 */
+#elif __CUDA_ARCH__ == 320
+# define CUDA_MULTIPRESSOR_MAX_REGISTERS 32768
+# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
+# define CUDA_BLOCK_MAX_THREADS 1024
+# define CUDA_THREAD_MAX_REGISTERS 63
+
+/* tunable parameters */
+# define CUDA_THREADS_BLOCK_WIDTH 16
+# define CUDA_KERNEL_MAX_REGISTERS 63
+# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
+/* 3.7 */
+#elif __CUDA_ARCH__ == 370
+# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
+# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 16
+# define CUDA_BLOCK_MAX_THREADS 1024
+# define CUDA_THREAD_MAX_REGISTERS 255
+
+/* tunable parameters */
+# define CUDA_THREADS_BLOCK_WIDTH 16
+# define CUDA_KERNEL_MAX_REGISTERS 63
+# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
+/* 5.0, 5.2, 5.3, 6.0, 6.1 */
+#elif __CUDA_ARCH__ >= 500
+# define CUDA_MULTIPRESSOR_MAX_REGISTERS 65536
+# define CUDA_MULTIPROCESSOR_MAX_BLOCKS 32
+# define CUDA_BLOCK_MAX_THREADS 1024
+# define CUDA_THREAD_MAX_REGISTERS 255
+
+/* tunable parameters */
+# define CUDA_THREADS_BLOCK_WIDTH 16
+# define CUDA_KERNEL_MAX_REGISTERS 48
+# define CUDA_KERNEL_BRANCHED_MAX_REGISTERS 63
+
+/* unknown architecture */
+#else
+# error "Unknown or unsupported CUDA architecture, can't determine launch bounds"
+#endif
+
+/* compute number of threads per block and minimum blocks per multiprocessor
+ * given the maximum number of registers per thread */
+
+#define CUDA_LAUNCH_BOUNDS(threads_block_width, thread_num_registers) \
+ __launch_bounds__( \
+ threads_block_width*threads_block_width, \
+ CUDA_MULTIPRESSOR_MAX_REGISTERS/(threads_block_width*threads_block_width*thread_num_registers) \
+ )
+
+/* sanity checks */
+
+#if CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH > CUDA_BLOCK_MAX_THREADS
+# error "Maximum number of threads per block exceeded"
+#endif
+
+#if CUDA_MULTIPRESSOR_MAX_REGISTERS/(CUDA_THREADS_BLOCK_WIDTH*CUDA_THREADS_BLOCK_WIDTH*CUDA_KERNEL_MAX_REGISTERS) > CUDA_MULTIPROCESSOR_MAX_BLOCKS
+# error "Maximum number of blocks per multiprocessor exceeded"
+#endif
+
+#if CUDA_KERNEL_MAX_REGISTERS > CUDA_THREAD_MAX_REGISTERS
+# error "Maximum number of registers per thread exceeded"
+#endif
+
+#if CUDA_KERNEL_BRANCHED_MAX_REGISTERS > CUDA_THREAD_MAX_REGISTERS
+# error "Maximum number of registers per thread exceeded"
+#endif
+
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_split.cu b/intern/cycles/kernel/kernels/cuda/kernel_split.cu
new file mode 100644
index 00000000000..a679eff8409
--- /dev/null
+++ b/intern/cycles/kernel/kernels/cuda/kernel_split.cu
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+/* CUDA split kernel entry points */
+
+#ifdef __CUDA_ARCH__
+
+#define __SPLIT_KERNEL__
+
+#include "kernel/kernel_compat_cuda.h"
+#include "kernel_config.h"
+
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_data_init.h"
+#include "kernel/split/kernel_path_init.h"
+#include "kernel/split/kernel_scene_intersect.h"
+#include "kernel/split/kernel_lamp_emission.h"
+#include "kernel/split/kernel_do_volume.h"
+#include "kernel/split/kernel_queue_enqueue.h"
+#include "kernel/split/kernel_indirect_background.h"
+#include "kernel/split/kernel_shader_eval.h"
+#include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
+#include "kernel/split/kernel_subsurface_scatter.h"
+#include "kernel/split/kernel_direct_lighting.h"
+#include "kernel/split/kernel_shadow_blocked_ao.h"
+#include "kernel/split/kernel_shadow_blocked_dl.h"
+#include "kernel/split/kernel_next_iteration_setup.h"
+#include "kernel/split/kernel_indirect_subsurface.h"
+#include "kernel/split/kernel_buffer_update.h"
+
+#include "kernel/kernel_film.h"
+
+/* kernels */
+extern "C" __global__ void
+CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
+kernel_cuda_state_buffer_size(uint num_threads, uint64_t *size)
+{
+ *size = split_data_buffer_size(NULL, num_threads);
+}
+
+extern "C" __global__ void
+CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
+kernel_cuda_path_trace_data_init(
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
+ ccl_global uint *rng_state,
+ int start_sample,
+ int end_sample,
+ int sx, int sy, int sw, int sh, int offset, int stride,
+ ccl_global int *Queue_index,
+ int queuesize,
+ ccl_global char *use_queues_flag,
+ ccl_global unsigned int *work_pool_wgs,
+ unsigned int num_samples,
+ ccl_global float *buffer)
+{
+ kernel_data_init(NULL,
+ NULL,
+ split_data_buffer,
+ num_elements,
+ ray_state,
+ rng_state,
+ start_sample,
+ end_sample,
+ sx, sy, sw, sh, offset, stride,
+ Queue_index,
+ queuesize,
+ use_queues_flag,
+ work_pool_wgs,
+ num_samples,
+ buffer);
+}
+
+#define DEFINE_SPLIT_KERNEL_FUNCTION(name) \
+ extern "C" __global__ void \
+ CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS) \
+ kernel_cuda_##name() \
+ { \
+ kernel_##name(NULL); \
+ }
+
+#define DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(name, type) \
+ extern "C" __global__ void \
+ CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS) \
+ kernel_cuda_##name() \
+ { \
+ ccl_local type locals; \
+ kernel_##name(NULL, &locals); \
+ }
+
+DEFINE_SPLIT_KERNEL_FUNCTION(path_init)
+DEFINE_SPLIT_KERNEL_FUNCTION(scene_intersect)
+DEFINE_SPLIT_KERNEL_FUNCTION(lamp_emission)
+DEFINE_SPLIT_KERNEL_FUNCTION(do_volume)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(queue_enqueue, QueueEnqueueLocals)
+DEFINE_SPLIT_KERNEL_FUNCTION(indirect_background)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(shader_eval, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(holdout_emission_blurring_pathtermination_ao, BackgroundAOLocals)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(subsurface_scatter, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(direct_lighting, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_ao)
+DEFINE_SPLIT_KERNEL_FUNCTION(shadow_blocked_dl)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(next_iteration_setup, uint)
+DEFINE_SPLIT_KERNEL_FUNCTION(indirect_subsurface)
+DEFINE_SPLIT_KERNEL_FUNCTION_LOCALS(buffer_update, uint)
+
+extern "C" __global__ void
+CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
+kernel_cuda_convert_to_byte(uchar4 *rgba, float *buffer, float sample_scale, int sx, int sy, int sw, int sh, int offset, int stride)
+{
+ int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
+ int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
+
+ if(x < sx + sw && y < sy + sh)
+ kernel_film_convert_to_byte(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+extern "C" __global__ void
+CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS)
+kernel_cuda_convert_to_half_float(uchar4 *rgba, float *buffer, float sample_scale, int sx, int sy, int sw, int sh, int offset, int stride)
+{
+ int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
+ int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
+
+ if(x < sx + sw && y < sy + sh)
+ kernel_film_convert_to_half_float(NULL, rgba, buffer, sample_scale, x, y, offset, stride);
+}
+
+#endif
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl
index a68f97857b6..078acc1631e 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel.cl
@@ -16,34 +16,34 @@
/* OpenCL kernel entry points - unfinished */
-#include "../../kernel_compat_opencl.h"
-#include "../../kernel_math.h"
-#include "../../kernel_types.h"
-#include "../../kernel_globals.h"
-#include "../../kernel_image_opencl.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/kernel_math.h"
+#include "kernel/kernel_types.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_image_opencl.h"
-#include "../../kernel_film.h"
+#include "kernel/kernel_film.h"
#if defined(__COMPILE_ONLY_MEGAKERNEL__) || !defined(__NO_BAKING__)
-# include "../../kernel_path.h"
-# include "../../kernel_path_branched.h"
+# include "kernel/kernel_path.h"
+# include "kernel/kernel_path_branched.h"
#else /* __COMPILE_ONLY_MEGAKERNEL__ */
/* Include only actually used headers for the case
* when path tracing kernels are not needed.
*/
-# include "../../kernel_random.h"
-# include "../../kernel_differential.h"
-# include "../../kernel_montecarlo.h"
-# include "../../kernel_projection.h"
-# include "../../geom/geom.h"
-# include "../../bvh/bvh.h"
-
-# include "../../kernel_accumulate.h"
-# include "../../kernel_camera.h"
-# include "../../kernel_shader.h"
+# include "kernel/kernel_random.h"
+# include "kernel/kernel_differential.h"
+# include "kernel/kernel_montecarlo.h"
+# include "kernel/kernel_projection.h"
+# include "kernel/geom/geom.h"
+# include "kernel/bvh/bvh.h"
+
+# include "kernel/kernel_accumulate.h"
+# include "kernel/kernel_camera.h"
+# include "kernel/kernel_shader.h"
#endif /* defined(__COMPILE_ONLY_MEGAKERNEL__) || !defined(__NO_BAKING__) */
-#include "../../kernel_bake.h"
+#include "kernel/kernel_bake.h"
#ifdef __COMPILE_ONLY_MEGAKERNEL__
@@ -54,7 +54,7 @@ __kernel void kernel_ocl_path_trace(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
int sample,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -65,10 +65,10 @@ __kernel void kernel_ocl_path_trace(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int x = sx + get_global_id(0);
- int y = sy + get_global_id(1);
+ int x = sx + ccl_global_id(0);
+ int y = sy + ccl_global_id(1);
if(x < sx + sw && y < sy + sh)
kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
@@ -84,7 +84,7 @@ __kernel void kernel_ocl_shader(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
int type, int sx, int sw, int offset, int sample)
{
@@ -94,9 +94,9 @@ __kernel void kernel_ocl_shader(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int x = sx + get_global_id(0);
+ int x = sx + ccl_global_id(0);
if(x < sx + sw) {
kernel_shader_evaluate(kg,
@@ -116,7 +116,7 @@ __kernel void kernel_ocl_bake(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
int type, int filter, int sx, int sw, int offset, int sample)
{
@@ -126,9 +126,9 @@ __kernel void kernel_ocl_bake(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int x = sx + get_global_id(0);
+ int x = sx + ccl_global_id(0);
if(x < sx + sw) {
#ifdef __NO_BAKING__
@@ -146,7 +146,7 @@ __kernel void kernel_ocl_convert_to_byte(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
float sample_scale,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -157,10 +157,10 @@ __kernel void kernel_ocl_convert_to_byte(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int x = sx + get_global_id(0);
- int y = sy + get_global_id(1);
+ int x = sx + ccl_global_id(0);
+ int y = sy + ccl_global_id(1);
if(x < sx + sw && y < sy + sh)
kernel_film_convert_to_byte(kg, rgba, buffer, sample_scale, x, y, offset, stride);
@@ -173,7 +173,7 @@ __kernel void kernel_ocl_convert_to_half_float(
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
float sample_scale,
int sx, int sy, int sw, int sh, int offset, int stride)
@@ -184,13 +184,29 @@ __kernel void kernel_ocl_convert_to_half_float(
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int x = sx + get_global_id(0);
- int y = sy + get_global_id(1);
+ int x = sx + ccl_global_id(0);
+ int y = sy + ccl_global_id(1);
if(x < sx + sw && y < sy + sh)
kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride);
}
+__kernel void kernel_ocl_zero_buffer(ccl_global float4 *buffer, ulong size, ulong offset)
+{
+ size_t i = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0);
+
+ if(i < size / sizeof(float4)) {
+ buffer[i+offset/sizeof(float4)] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ else if(i == size / sizeof(float4)) {
+ ccl_global uchar *b = (ccl_global uchar*)&buffer[i+offset/sizeof(float4)];
+
+ for(i = 0; i < size % sizeof(float4); i++) {
+ *(b++) = 0;
+ }
+ }
+}
+
#endif /* __COMPILE_ONLY_MEGAKERNEL__ */
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl b/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl
deleted file mode 100644
index 1914d241eb1..00000000000
--- a/intern/cycles/kernel/kernels/opencl/kernel_background_buffer_update.cl
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 2011-2015 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 "split/kernel_background_buffer_update.h"
-
-__kernel void kernel_ocl_path_trace_background_buffer_update(
- ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global float *per_sample_output_buffers,
- ccl_global uint *rng_state,
- ccl_global uint *rng_coop, /* Required for buffer Update */
- ccl_global float3 *throughput_coop, /* Required for background hit processing */
- PathRadiance *PathRadiance_coop, /* Required for background hit processing and buffer Update */
- ccl_global Ray *Ray_coop, /* Required for background hit processing */
- ccl_global PathState *PathState_coop, /* Required for background hit processing */
- ccl_global float *L_transparent_coop, /* Required for background hit processing and buffer Update */
- ccl_global char *ray_state, /* Stores information on the current state of a ray */
- int sw, int sh, int sx, int sy, int stride,
- int rng_state_offset_x,
- int rng_state_offset_y,
- int rng_state_stride,
- ccl_global unsigned int *work_array, /* Denotes work of each ray */
- ccl_global int *Queue_data, /* Queues memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize, /* Size (capacity) of each queue */
- int end_sample,
- int start_sample,
-#ifdef __WORK_STEALING__
- ccl_global unsigned int *work_pool_wgs,
- unsigned int num_samples,
-#endif
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int parallel_samples) /* Number of samples to be processed in parallel */
-{
- ccl_local unsigned int local_queue_atomics;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_queue_atomics = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- if(ray_index == 0) {
- /* We will empty this queue in this kernel. */
- Queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
- }
- char enqueue_flag = 0;
- ray_index = get_ray_index(ray_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- Queue_data,
- queuesize,
- 1);
-
-#ifdef __COMPUTE_DEVICE_GPU__
- /* If we are executing on a GPU device, we exit all threads that are not
- * required.
- *
- * If we are executing on a CPU device, then we need to keep all threads
- * active since we have barrier() calls later in the kernel. CPU devices,
- * expect all threads to execute barrier statement.
- */
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
-#endif
-
-#ifndef __COMPUTE_DEVICE_GPU__
- if(ray_index != QUEUE_EMPTY_SLOT) {
-#endif
- enqueue_flag =
- kernel_background_buffer_update((KernelGlobals *)kg,
- per_sample_output_buffers,
- rng_state,
- rng_coop,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- L_transparent_coop,
- ray_state,
- sw, sh, sx, sy, stride,
- rng_state_offset_x,
- rng_state_offset_y,
- rng_state_stride,
- work_array,
- end_sample,
- start_sample,
-#ifdef __WORK_STEALING__
- work_pool_wgs,
- num_samples,
-#endif
-#ifdef __KERNEL_DEBUG__
- debugdata_coop,
-#endif
- parallel_samples,
- ray_index);
-#ifndef __COMPUTE_DEVICE_GPU__
- }
-#endif
-
- /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS;
- * These rays will be made active during next SceneIntersectkernel.
- */
- enqueue_ray_index_local(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- enqueue_flag,
- queuesize,
- &local_queue_atomics,
- Queue_data,
- Queue_index);
-}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl b/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl
new file mode 100644
index 00000000000..db65c91baf7
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_buffer_update.cl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011-2015 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_buffer_update.h"
+
+__kernel void kernel_ocl_path_trace_buffer_update(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ ccl_local unsigned int local_queue_atomics;
+ kernel_buffer_update((KernelGlobals*)kg, &local_queue_atomics);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
index 18139687eab..8b85d362f8a 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_data_init.cl
@@ -14,77 +14,49 @@
* limitations under the License.
*/
-#include "split/kernel_data_init.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_data_init.h"
__kernel void kernel_ocl_path_trace_data_init(
- ccl_global char *globals,
- ccl_global char *sd_DL_shadow,
+ ccl_global char *kg,
ccl_constant KernelData *data,
- ccl_global float *per_sample_output_buffers,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
ccl_global uint *rng_state,
- ccl_global uint *rng_coop, /* rng array to store rng values for all rays */
- ccl_global float3 *throughput_coop, /* throughput array to store throughput values for all rays */
- ccl_global float *L_transparent_coop, /* L_transparent array to store L_transparent values for all rays */
- PathRadiance *PathRadiance_coop, /* PathRadiance array to store PathRadiance values for all rays */
- ccl_global Ray *Ray_coop, /* Ray array to store Ray information for all rays */
- ccl_global PathState *PathState_coop, /* PathState array to store PathState information for all rays */
- Intersection *Intersection_coop_shadow,
- ccl_global char *ray_state, /* Stores information on current state of a ray */
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- int start_sample, int sx, int sy, int sw, int sh, int offset, int stride,
- int rng_state_offset_x,
- int rng_state_offset_y,
- int rng_state_stride,
- ccl_global int *Queue_data, /* Memory for queues */
+ int start_sample,
+ int end_sample,
+ int sx, int sy, int sw, int sh, int offset, int stride,
ccl_global int *Queue_index, /* Tracks the number of elements in queues */
int queuesize, /* size (capacity) of the queue */
ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
- ccl_global unsigned int *work_array, /* work array to store which work each ray belongs to */
-#ifdef __WORK_STEALING__
ccl_global unsigned int *work_pool_wgs, /* Work pool for each work group */
unsigned int num_samples, /* Total number of samples per pixel */
-#endif
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int parallel_samples) /* Number of samples to be processed in parallel */
+ ccl_global float *buffer)
{
- kernel_data_init((KernelGlobals *)globals,
- (ShaderData *)sd_DL_shadow,
+ kernel_data_init((KernelGlobals*)kg,
data,
- per_sample_output_buffers,
- rng_state,
- rng_coop,
- throughput_coop,
- L_transparent_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop_shadow,
+ split_data_buffer,
+ num_elements,
ray_state,
+ rng_state,
#define KERNEL_TEX(type, ttype, name) name,
-#include "../../kernel_textures.h"
+#include "kernel/kernel_textures.h"
- start_sample, sx, sy, sw, sh, offset, stride,
- rng_state_offset_x,
- rng_state_offset_y,
- rng_state_stride,
- Queue_data,
+ start_sample,
+ end_sample,
+ sx, sy, sw, sh, offset, stride,
Queue_index,
queuesize,
use_queues_flag,
- work_array,
-#ifdef __WORK_STEALING__
work_pool_wgs,
num_samples,
-#endif
-#ifdef __KERNEL_DEBUG__
- debugdata_coop,
-#endif
- parallel_samples);
+ buffer);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
index c6a2c8d050c..eb34f750881 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_direct_lighting.cl
@@ -14,74 +14,14 @@
* limitations under the License.
*/
-#include "split/kernel_direct_lighting.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_direct_lighting.h"
__kernel void kernel_ocl_path_trace_direct_lighting(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global char *sd, /* Required for direct lighting */
- ccl_global uint *rng_coop, /* Required for direct lighting */
- ccl_global PathState *PathState_coop, /* Required for direct lighting */
- ccl_global int *ISLamp_coop, /* Required for direct lighting */
- ccl_global Ray *LightRay_coop, /* Required for direct lighting */
- ccl_global BsdfEval *BSDFEval_coop, /* Required for direct lighting */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global int *Queue_data, /* Queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize) /* Size (capacity) of each queue */
+ ccl_constant KernelData *data)
{
ccl_local unsigned int local_queue_atomics;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_queue_atomics = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- char enqueue_flag = 0;
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 0);
-
-#ifdef __COMPUTE_DEVICE_GPU__
- /* If we are executing on a GPU device, we exit all threads that are not
- * required.
- *
- * If we are executing on a CPU device, then we need to keep all threads
- * active since we have barrier() calls later in the kernel. CPU devices,
- * expect all threads to execute barrier statement.
- */
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
-#endif
-
-#ifndef __COMPUTE_DEVICE_GPU__
- if(ray_index != QUEUE_EMPTY_SLOT) {
-#endif
- enqueue_flag = kernel_direct_lighting((KernelGlobals *)kg,
- (ShaderData *)sd,
- rng_coop,
- PathState_coop,
- ISLamp_coop,
- LightRay_coop,
- BSDFEval_coop,
- ray_state,
- ray_index);
-
-#ifndef __COMPUTE_DEVICE_GPU__
- }
-#endif
-
-#ifdef __EMISSION__
- /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_SHADOW_RAY_CAST_DL_RAYS,
- enqueue_flag,
- queuesize,
- &local_queue_atomics,
- Queue_data,
- Queue_index);
-#endif
+ kernel_direct_lighting((KernelGlobals*)kg, &local_queue_atomics);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl b/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl
new file mode 100644
index 00000000000..83ef5f5f3f2
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_do_volume.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_do_volume.h"
+
+__kernel void kernel_ocl_path_trace_do_volume(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_do_volume((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
index e063614da1a..d071b39aa6f 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl
@@ -14,110 +14,16 @@
* limitations under the License.
*/
-#include "split/kernel_holdout_emission_blurring_pathtermination_ao.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h"
__kernel void kernel_ocl_path_trace_holdout_emission_blurring_pathtermination_ao(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global char *sd, /* Required throughout the kernel except probabilistic path termination and AO */
- ccl_global float *per_sample_output_buffers,
- ccl_global uint *rng_coop, /* Required for "kernel_write_data_passes" and AO */
- ccl_global float3 *throughput_coop, /* Required for handling holdout material and AO */
- ccl_global float *L_transparent_coop, /* Required for handling holdout material */
- PathRadiance *PathRadiance_coop, /* Required for "kernel_write_data_passes" and indirect primitive emission */
- ccl_global PathState *PathState_coop, /* Required throughout the kernel and AO */
- Intersection *Intersection_coop, /* Required for indirect primitive emission */
- ccl_global float3 *AOAlpha_coop, /* Required for AO */
- ccl_global float3 *AOBSDF_coop, /* Required for AO */
- ccl_global Ray *AOLightRay_coop, /* Required for AO */
- int sw, int sh, int sx, int sy, int stride,
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global unsigned int *work_array, /* Denotes the work that each ray belongs to */
- ccl_global int *Queue_data, /* Queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize, /* Size (capacity) of each queue */
-#ifdef __WORK_STEALING__
- unsigned int start_sample,
-#endif
- int parallel_samples) /* Number of samples to be processed in parallel */
+ ccl_constant KernelData *data)
{
- ccl_local unsigned int local_queue_atomics_bg;
- ccl_local unsigned int local_queue_atomics_ao;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_queue_atomics_bg = 0;
- local_queue_atomics_ao = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- char enqueue_flag = 0;
- char enqueue_flag_AO_SHADOW_RAY_CAST = 0;
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 0);
-
-#ifdef __COMPUTE_DEVICE_GPU__
- /* If we are executing on a GPU device, we exit all threads that are not
- * required.
- *
- * If we are executing on a CPU device, then we need to keep all threads
- * active since we have barrier() calls later in the kernel. CPU devices,
- * expect all threads to execute barrier statement.
- */
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
-#endif /* __COMPUTE_DEVICE_GPU__ */
-
-#ifndef __COMPUTE_DEVICE_GPU__
- if(ray_index != QUEUE_EMPTY_SLOT) {
-#endif
- kernel_holdout_emission_blurring_pathtermination_ao(
- (KernelGlobals *)kg,
- (ShaderData *)sd,
- per_sample_output_buffers,
- rng_coop,
- throughput_coop,
- L_transparent_coop,
- PathRadiance_coop,
- PathState_coop,
- Intersection_coop,
- AOAlpha_coop,
- AOBSDF_coop,
- AOLightRay_coop,
- sw, sh, sx, sy, stride,
- ray_state,
- work_array,
-#ifdef __WORK_STEALING__
- start_sample,
-#endif
- parallel_samples,
- ray_index,
- &enqueue_flag,
- &enqueue_flag_AO_SHADOW_RAY_CAST);
-#ifndef __COMPUTE_DEVICE_GPU__
- }
-#endif
-
- /* Enqueue RAY_UPDATE_BUFFER rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- enqueue_flag,
- queuesize,
- &local_queue_atomics_bg,
- Queue_data,
- Queue_index);
-
-#ifdef __AO__
- /* Enqueue to-shadow-ray-cast rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_SHADOW_RAY_CAST_AO_RAYS,
- enqueue_flag_AO_SHADOW_RAY_CAST,
- queuesize,
- &local_queue_atomics_ao,
- Queue_data,
- Queue_index);
-#endif
+ ccl_local BackgroundAOLocals locals;
+ kernel_holdout_emission_blurring_pathtermination_ao(
+ (KernelGlobals*)kg,
+ &locals);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl b/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl
new file mode 100644
index 00000000000..8c213ff5cb2
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_indirect_background.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_indirect_background.h"
+
+__kernel void kernel_ocl_path_trace_indirect_background(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_indirect_background((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl b/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl
new file mode 100644
index 00000000000..998ebc4c0c3
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_indirect_subsurface.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_indirect_subsurface.h"
+
+__kernel void kernel_ocl_path_trace_indirect_subsurface(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_indirect_subsurface((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
index 267bddc2ffc..822d2287715 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_lamp_emission.cl
@@ -14,67 +14,13 @@
* limitations under the License.
*/
-#include "split/kernel_lamp_emission.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_lamp_emission.h"
__kernel void kernel_ocl_path_trace_lamp_emission(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global float3 *throughput_coop, /* Required for lamp emission */
- PathRadiance *PathRadiance_coop, /* Required for lamp emission */
- ccl_global Ray *Ray_coop, /* Required for lamp emission */
- ccl_global PathState *PathState_coop, /* Required for lamp emission */
- Intersection *Intersection_coop, /* Required for lamp emission */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int sw, int sh,
- ccl_global int *Queue_data, /* Memory for queues */
- ccl_global int *Queue_index, /* Tracks the number of elements in queues */
- int queuesize, /* Size (capacity) of queues */
- ccl_global char *use_queues_flag, /* Used to decide if this kernel should use
- * queues to fetch ray index
- */
- int parallel_samples) /* Number of samples to be processed in parallel */
+ ccl_constant KernelData *data)
{
- int x = get_global_id(0);
- int y = get_global_id(1);
-
- /* We will empty this queue in this kernel. */
- if(get_global_id(0) == 0 && get_global_id(1) == 0) {
- Queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
- }
- /* Fetch use_queues_flag. */
- ccl_local char local_use_queues_flag;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_use_queues_flag = use_queues_flag[0];
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- int ray_index;
- if(local_use_queues_flag) {
- int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(thread_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 1);
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
- } else {
- if(x < (sw * parallel_samples) && y < sh) {
- ray_index = x + y * (sw * parallel_samples);
- } else {
- return;
- }
- }
-
- kernel_lamp_emission((KernelGlobals *)kg,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- sw, sh,
- use_queues_flag,
- ray_index);
+ kernel_lamp_emission((KernelGlobals*)kg);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
index 6d49b6294a8..6d207253a40 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_next_iteration_setup.cl
@@ -14,101 +14,14 @@
* limitations under the License.
*/
-#include "split/kernel_next_iteration_setup.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_next_iteration_setup.h"
__kernel void kernel_ocl_path_trace_next_iteration_setup(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global char *sd, /* Required for setting up ray for next iteration */
- ccl_global uint *rng_coop, /* Required for setting up ray for next iteration */
- ccl_global float3 *throughput_coop, /* Required for setting up ray for next iteration */
- PathRadiance *PathRadiance_coop, /* Required for setting up ray for next iteration */
- ccl_global Ray *Ray_coop, /* Required for setting up ray for next iteration */
- ccl_global PathState *PathState_coop, /* Required for setting up ray for next iteration */
- ccl_global Ray *LightRay_dl_coop, /* Required for radiance update - direct lighting */
- ccl_global int *ISLamp_coop, /* Required for radiance update - direct lighting */
- ccl_global BsdfEval *BSDFEval_coop, /* Required for radiance update - direct lighting */
- ccl_global Ray *LightRay_ao_coop, /* Required for radiance update - AO */
- ccl_global float3 *AOBSDF_coop, /* Required for radiance update - AO */
- ccl_global float3 *AOAlpha_coop, /* Required for radiance update - AO */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global int *Queue_data, /* Queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize, /* Size (capacity) of each queue */
- ccl_global char *use_queues_flag) /* flag to decide if scene_intersect kernel should
- * use queues to fetch ray index */
+ ccl_constant KernelData *data)
{
ccl_local unsigned int local_queue_atomics;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_queue_atomics = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if(get_global_id(0) == 0 && get_global_id(1) == 0) {
- /* If we are here, then it means that scene-intersect kernel
- * has already been executed atleast once. From the next time,
- * scene-intersect kernel may operate on queues to fetch ray index
- */
- use_queues_flag[0] = 1;
-
- /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and
- * QUEUE_SHADOW_RAY_CAST_DL_RAYS queues that were made empty during the
- * previous kernel.
- */
- Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
- Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
- }
-
- char enqueue_flag = 0;
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 0);
-
-#ifdef __COMPUTE_DEVICE_GPU__
- /* If we are executing on a GPU device, we exit all threads that are not
- * required.
- *
- * If we are executing on a CPU device, then we need to keep all threads
- * active since we have barrier() calls later in the kernel. CPU devices,
- * expect all threads to execute barrier statement.
- */
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
-#endif
-
-#ifndef __COMPUTE_DEVICE_GPU__
- if(ray_index != QUEUE_EMPTY_SLOT) {
-#endif
- enqueue_flag = kernel_next_iteration_setup((KernelGlobals *)kg,
- (ShaderData *)sd,
- rng_coop,
- throughput_coop,
- PathRadiance_coop,
- Ray_coop,
- PathState_coop,
- LightRay_dl_coop,
- ISLamp_coop,
- BSDFEval_coop,
- LightRay_ao_coop,
- AOBSDF_coop,
- AOAlpha_coop,
- ray_state,
- use_queues_flag,
- ray_index);
-#ifndef __COMPUTE_DEVICE_GPU__
- }
-#endif
-
- /* Enqueue RAY_UPDATE_BUFFER rays. */
- enqueue_ray_index_local(ray_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- enqueue_flag,
- queuesize,
- &local_queue_atomics,
- Queue_data,
- Queue_index);
+ kernel_next_iteration_setup((KernelGlobals*)kg, &local_queue_atomics);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl b/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl
new file mode 100644
index 00000000000..bd9aa9538c8
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_path_init.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_path_init.h"
+
+__kernel void kernel_ocl_path_trace_path_init(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_path_init((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
index 3156dc255fb..9be154e3d75 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_queue_enqueue.cl
@@ -14,93 +14,14 @@
* limitations under the License.
*/
-#include "../../kernel_compat_opencl.h"
-#include "../../kernel_math.h"
-#include "../../kernel_types.h"
-#include "../../kernel_globals.h"
-#include "../../kernel_queues.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_queue_enqueue.h"
-/*
- * The kernel "kernel_queue_enqueue" enqueues rays of
- * different ray state into their appropriate Queues;
- * 1. Rays that have been determined to hit the background from the
- * "kernel_scene_intersect" kernel
- * are enqueued in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
- * 2. Rays that have been determined to be actively participating in path-iteration will be enqueued into QUEUE_ACTIVE_AND_REGENERATED_RAYS.
- *
- * The input and output of the kernel is as follows,
- *
- * ray_state -------------------------------------------|--- kernel_queue_enqueue --|--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
- * Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS & QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
- * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |
- * queuesize -------------------------------------------| |
- *
- * Note on Queues :
- * State of queues during the first time this kernel is called :
- * At entry,
- * Both QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.
- * At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays
- * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_HIT_BACKGROUND rays.
- *
- * State of queue during other times this kernel is called :
- * At entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be empty.
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will contain RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays.
- * At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays.
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE, RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND rays.
- */
__kernel void kernel_ocl_path_trace_queue_enqueue(
- ccl_global int *Queue_data, /* Queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int queuesize) /* Size (capacity) of each queue */
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
{
- /* We have only 2 cases (Hit/Not-Hit) */
- ccl_local unsigned int local_queue_atomics[2];
-
- int lidx = get_local_id(1) * get_local_size(0) + get_local_id(0);
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
-
- if(lidx < 2 ) {
- local_queue_atomics[lidx] = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- int queue_number = -1;
-
- if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
- queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
- }
- else if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS;
- }
-
- unsigned int my_lqidx;
- if(queue_number != -1) {
- my_lqidx = get_local_queue_index(queue_number, local_queue_atomics);
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if(lidx == 0) {
- local_queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] =
- get_global_per_queue_offset(QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- local_queue_atomics,
- Queue_index);
- local_queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] =
- get_global_per_queue_offset(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- local_queue_atomics,
- Queue_index);
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- unsigned int my_gqidx;
- if(queue_number != -1) {
- my_gqidx = get_global_queue_index(queue_number,
- queuesize,
- my_lqidx,
- local_queue_atomics);
- Queue_data[my_gqidx] = ray_index;
- }
+ ccl_local QueueEnqueueLocals locals;
+ kernel_queue_enqueue((KernelGlobals*)kg, &locals);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
index 7f3f433c7a6..eb4fb4d153a 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_scene_intersect.cl
@@ -14,67 +14,13 @@
* limitations under the License.
*/
-#include "split/kernel_scene_intersect.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_scene_intersect.h"
__kernel void kernel_ocl_path_trace_scene_intersect(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global uint *rng_coop,
- ccl_global Ray *Ray_coop, /* Required for scene_intersect */
- ccl_global PathState *PathState_coop, /* Required for scene_intersect */
- Intersection *Intersection_coop, /* Required for scene_intersect */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int sw, int sh,
- ccl_global int *Queue_data, /* Memory for queues */
- ccl_global int *Queue_index, /* Tracks the number of elements in queues */
- int queuesize, /* Size (capacity) of queues */
- ccl_global char *use_queues_flag, /* used to decide if this kernel should use
- * queues to fetch ray index */
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int parallel_samples) /* Number of samples to be processed in parallel */
+ ccl_constant KernelData *data)
{
- int x = get_global_id(0);
- int y = get_global_id(1);
-
- /* Fetch use_queues_flag */
- ccl_local char local_use_queues_flag;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_use_queues_flag = use_queues_flag[0];
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- int ray_index;
- if(local_use_queues_flag) {
- int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(thread_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 0);
-
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
- } else {
- if(x < (sw * parallel_samples) && y < sh) {
- ray_index = x + y * (sw * parallel_samples);
- } else {
- return;
- }
- }
-
- kernel_scene_intersect((KernelGlobals *)kg,
- rng_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- sw, sh,
- use_queues_flag,
-#ifdef __KERNEL_DEBUG__
- debugdata_coop,
-#endif
- ray_index);
+ kernel_scene_intersect((KernelGlobals*)kg);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
index c37856c8f30..6baee460986 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shader_eval.cl
@@ -14,55 +14,14 @@
* limitations under the License.
*/
-#include "split/kernel_shader_eval.h"
+#include "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_shader_eval.h"
__kernel void kernel_ocl_path_trace_shader_eval(
ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global char *sd, /* Output ShaderData structure to be filled */
- ccl_global uint *rng_coop, /* Required for rbsdf calculation */
- ccl_global Ray *Ray_coop, /* Required for setting up shader from ray */
- ccl_global PathState *PathState_coop, /* Required for all functions in this kernel */
- Intersection *Intersection_coop, /* Required for setting up shader from ray */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global int *Queue_data, /* queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize) /* Size (capacity) of each queue */
+ ccl_constant KernelData *data)
{
- /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
ccl_local unsigned int local_queue_atomics;
- if(get_local_id(0) == 0 && get_local_id(1) == 0) {
- local_queue_atomics = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- int ray_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- ray_index = get_ray_index(ray_index,
- QUEUE_ACTIVE_AND_REGENERATED_RAYS,
- Queue_data,
- queuesize,
- 0);
-
- if(ray_index == QUEUE_EMPTY_SLOT) {
- return;
- }
-
- char enqueue_flag = (IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) ? 1 : 0;
- enqueue_ray_index_local(ray_index,
- QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
- enqueue_flag,
- queuesize,
- &local_queue_atomics,
- Queue_data,
- Queue_index);
-
- /* Continue on with shader evaluation. */
- kernel_shader_eval((KernelGlobals *)kg,
- (ShaderData *)sd,
- rng_coop,
- Ray_coop,
- PathState_coop,
- Intersection_coop,
- ray_state,
- ray_index);
+ kernel_shader_eval((KernelGlobals*)kg, &local_queue_atomics);
}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl
deleted file mode 100644
index edf76fba714..00000000000
--- a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked.cl
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2011-2015 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 "split/kernel_shadow_blocked.h"
-
-__kernel void kernel_ocl_path_trace_shadow_blocked(
- ccl_global char *kg,
- ccl_constant KernelData *data,
- ccl_global PathState *PathState_coop, /* Required for shadow blocked */
- ccl_global Ray *LightRay_dl_coop, /* Required for direct lighting's shadow blocked */
- ccl_global Ray *LightRay_ao_coop, /* Required for AO's shadow blocked */
- ccl_global char *ray_state,
- ccl_global int *Queue_data, /* Queue memory */
- ccl_global int *Queue_index, /* Tracks the number of elements in each queue */
- int queuesize) /* Size (capacity) of each queue */
-{
- int lidx = get_local_id(1) * get_local_id(0) + get_local_id(0);
-
- ccl_local unsigned int ao_queue_length;
- ccl_local unsigned int dl_queue_length;
- if(lidx == 0) {
- ao_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS];
- dl_queue_length = Queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS];
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- /* flag determining if the current ray is to process shadow ray for AO or DL */
- char shadow_blocked_type = -1;
-
- int ray_index = QUEUE_EMPTY_SLOT;
- int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
- if(thread_index < ao_queue_length + dl_queue_length) {
- if(thread_index < ao_queue_length) {
- ray_index = get_ray_index(thread_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS, Queue_data, queuesize, 1);
- shadow_blocked_type = RAY_SHADOW_RAY_CAST_AO;
- } else {
- ray_index = get_ray_index(thread_index - ao_queue_length, QUEUE_SHADOW_RAY_CAST_DL_RAYS, Queue_data, queuesize, 1);
- shadow_blocked_type = RAY_SHADOW_RAY_CAST_DL;
- }
- }
-
- if(ray_index == QUEUE_EMPTY_SLOT)
- return;
-
- kernel_shadow_blocked((KernelGlobals *)kg,
- PathState_coop,
- LightRay_dl_coop,
- LightRay_ao_coop,
- ray_state,
- shadow_blocked_type,
- ray_index);
-}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl
new file mode 100644
index 00000000000..6a8ef81b32a
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_ao.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2015 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_shadow_blocked_ao.h"
+
+__kernel void kernel_ocl_path_trace_shadow_blocked_ao(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_shadow_blocked_ao((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl
new file mode 100644
index 00000000000..b255cc5ef8b
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_shadow_blocked_dl.cl
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011-2015 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_shadow_blocked_dl.h"
+
+__kernel void kernel_ocl_path_trace_shadow_blocked_dl(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ kernel_shadow_blocked_dl((KernelGlobals*)kg);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_split.cl b/intern/cycles/kernel/kernels/opencl/kernel_split.cl
new file mode 100644
index 00000000000..732cda30115
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_split.cl
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernels/opencl/kernel_state_buffer_size.cl"
+#include "kernel/kernels/opencl/kernel_data_init.cl"
+#include "kernel/kernels/opencl/kernel_path_init.cl"
+
+#include "kernel/kernels/opencl/kernel_scene_intersect.cl"
+#include "kernel/kernels/opencl/kernel_lamp_emission.cl"
+#include "kernel/kernels/opencl/kernel_do_volume.cl"
+#include "kernel/kernels/opencl/kernel_indirect_background.cl"
+#include "kernel/kernels/opencl/kernel_queue_enqueue.cl"
+#include "kernel/kernels/opencl/kernel_shader_eval.cl"
+#include "kernel/kernels/opencl/kernel_holdout_emission_blurring_pathtermination_ao.cl"
+#include "kernel/kernels/opencl/kernel_subsurface_scatter.cl"
+#include "kernel/kernels/opencl/kernel_direct_lighting.cl"
+#include "kernel/kernels/opencl/kernel_shadow_blocked_ao.cl"
+#include "kernel/kernels/opencl/kernel_shadow_blocked_dl.cl"
+#include "kernel/kernels/opencl/kernel_next_iteration_setup.cl"
+#include "kernel/kernels/opencl/kernel_indirect_subsurface.cl"
+#include "kernel/kernels/opencl/kernel_buffer_update.cl"
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_state_buffer_size.cl b/intern/cycles/kernel/kernels/opencl/kernel_state_buffer_size.cl
new file mode 100644
index 00000000000..c10ecc426c6
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_state_buffer_size.cl
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+
+__kernel void kernel_ocl_path_trace_state_buffer_size(
+ ccl_global char *kg,
+ ccl_constant KernelData *data,
+ uint num_threads,
+ ccl_global uint64_t *size)
+{
+ ((KernelGlobals*)kg)->data = data;
+ *size = split_data_buffer_size((KernelGlobals*)kg, num_threads);
+}
+
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl
new file mode 100644
index 00000000000..7a1838e485f
--- /dev/null
+++ b/intern/cycles/kernel/kernels/opencl/kernel_subsurface_scatter.cl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011-2017 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 "kernel/kernel_compat_opencl.h"
+#include "kernel/split/kernel_split_common.h"
+#include "kernel/split/kernel_subsurface_scatter.h"
+
+__kernel void kernel_ocl_path_trace_subsurface_scatter(
+ ccl_global char *kg,
+ ccl_constant KernelData *data)
+{
+ ccl_local unsigned int local_queue_atomics;
+ kernel_subsurface_scatter((KernelGlobals*)kg, &local_queue_atomics);
+}
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl b/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl
deleted file mode 100644
index 88a1ed830af..00000000000
--- a/intern/cycles/kernel/kernels/opencl/kernel_sum_all_radiance.cl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2011-2015 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 "split/kernel_sum_all_radiance.h"
-
-__kernel void kernel_ocl_path_trace_sum_all_radiance(
- ccl_constant KernelData *data, /* To get pass_stride to offet into buffer */
- ccl_global float *buffer, /* Output buffer of RenderTile */
- ccl_global float *per_sample_output_buffer, /* Radiance contributed by all samples */
- int parallel_samples, int sw, int sh, int stride,
- int buffer_offset_x,
- int buffer_offset_y,
- int buffer_stride,
- int start_sample)
-{
- kernel_sum_all_radiance(data,
- buffer,
- per_sample_output_buffer,
- parallel_samples,
- sw, sh, stride,
- buffer_offset_x,
- buffer_offset_y,
- buffer_stride,
- start_sample);
-}
diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt
index 98de40e5a8a..d2eb89e0e0a 100644
--- a/intern/cycles/kernel/osl/CMakeLists.txt
+++ b/intern/cycles/kernel/osl/CMakeLists.txt
@@ -1,12 +1,6 @@
set(INC
- .
- ..
- ../svm
- ../../graph
- ../../render
- ../../util
- ../../device
+ ../..
)
set(INC_SYS
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index d835f9be45c..2e73e7a601e 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -34,10 +34,10 @@
#include <OSL/genclosure.h>
-#include "osl_closures.h"
+#include "kernel/osl/osl_closures.h"
-#include "kernel_compat_cpu.h"
-#include "closure/alloc.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/closure/alloc.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
index bc26f42b559..ea18f2c8c86 100644
--- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
@@ -34,13 +34,13 @@
#include <OSL/genclosure.h>
-#include "kernel_compat_cpu.h"
-#include "osl_closures.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/osl/osl_closures.h"
-#include "kernel_types.h"
-#include "kernel_montecarlo.h"
-#include "closure/alloc.h"
-#include "closure/bsdf_diffuse_ramp.h"
+#include "kernel/kernel_types.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_diffuse_ramp.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
index 14c7644936e..a26671eb09e 100644
--- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
+++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
@@ -34,12 +34,12 @@
#include <OSL/genclosure.h>
-#include "kernel_compat_cpu.h"
-#include "osl_closures.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/osl/osl_closures.h"
-#include "kernel_types.h"
-#include "closure/alloc.h"
-#include "closure/bsdf_phong_ramp.h"
+#include "kernel/kernel_types.h"
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_phong_ramp.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp
index 3f13e08b302..8843a196dad 100644
--- a/intern/cycles/kernel/osl/emissive.cpp
+++ b/intern/cycles/kernel/osl/emissive.cpp
@@ -34,12 +34,12 @@
#include <OSL/genclosure.h>
-#include "osl_closures.h"
+#include "kernel/osl/osl_closures.h"
-#include "kernel_compat_cpu.h"
-#include "kernel_types.h"
-#include "closure/alloc.h"
-#include "closure/emissive.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/kernel_types.h"
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/emissive.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp
index 3614717e28c..95beea01d25 100644
--- a/intern/cycles/kernel/osl/osl_bssrdf.cpp
+++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp
@@ -32,15 +32,15 @@
#include <OSL/genclosure.h>
-#include "kernel_compat_cpu.h"
-#include "osl_closures.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/osl/osl_closures.h"
-#include "kernel_types.h"
-#include "kernel_montecarlo.h"
+#include "kernel/kernel_types.h"
+#include "kernel/kernel_montecarlo.h"
-#include "closure/alloc.h"
-#include "closure/bsdf_diffuse.h"
-#include "closure/bssrdf.h"
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bssrdf.h"
CCL_NAMESPACE_BEGIN
@@ -78,7 +78,7 @@ public:
bssrdf->albedo = albedo.x;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
@@ -89,7 +89,7 @@ public:
bssrdf->albedo = albedo.y;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
@@ -100,7 +100,7 @@ public:
bssrdf->albedo = albedo.z;
bssrdf->sharpness = sharpness;
bssrdf->N = params.N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
}
}
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index 94de782dca0..f44714c2150 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -33,33 +33,34 @@
#include <OSL/genclosure.h>
#include <OSL/oslclosure.h>
-#include "osl_closures.h"
-#include "osl_shader.h"
-
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_param.h"
-
-#include "kernel_types.h"
-#include "kernel_compat_cpu.h"
-#include "kernel_globals.h"
-#include "kernel_montecarlo.h"
-#include "kernel_random.h"
-
-#include "closure/alloc.h"
-#include "closure/bsdf_util.h"
-#include "closure/bsdf_ashikhmin_velvet.h"
-#include "closure/bsdf_diffuse.h"
-#include "closure/bsdf_microfacet.h"
-#include "closure/bsdf_microfacet_multi.h"
-#include "closure/bsdf_oren_nayar.h"
-#include "closure/bsdf_reflection.h"
-#include "closure/bsdf_refraction.h"
-#include "closure/bsdf_transparent.h"
-#include "closure/bsdf_ashikhmin_shirley.h"
-#include "closure/bsdf_toon.h"
-#include "closure/bsdf_hair.h"
-#include "closure/volume.h"
+#include "kernel/osl/osl_closures.h"
+#include "kernel/osl/osl_shader.h"
+
+#include "util/util_debug.h"
+#include "util/util_math.h"
+#include "util/util_param.h"
+
+#include "kernel/kernel_types.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/split/kernel_split_data_types.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/kernel_random.h"
+
+#include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_util.h"
+#include "kernel/closure/bsdf_ashikhmin_velvet.h"
+#include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bsdf_microfacet.h"
+#include "kernel/closure/bsdf_microfacet_multi.h"
+#include "kernel/closure/bsdf_oren_nayar.h"
+#include "kernel/closure/bsdf_reflection.h"
+#include "kernel/closure/bsdf_refraction.h"
+#include "kernel/closure/bsdf_transparent.h"
+#include "kernel/closure/bsdf_ashikhmin_shirley.h"
+#include "kernel/closure/bsdf_toon.h"
+#include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/volume.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index cd7b33703ff..929cf00a7e6 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -33,8 +33,8 @@
#ifndef __OSL_CLOSURES_H__
#define __OSL_CLOSURES_H__
-#include "util_types.h"
-#include "kernel_types.h"
+#include "util/util_types.h"
+#include "kernel/kernel_types.h"
#include <OSL/oslclosure.h>
#include <OSL/oslexec.h>
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 65cb7ecc6b4..02c083a83f8 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -21,10 +21,10 @@
#include <OSL/oslexec.h>
-#include "util_map.h"
-#include "util_param.h"
-#include "util_thread.h"
-#include "util_vector.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_thread.h"
+#include "util/util_vector.h"
#ifndef WIN32
using std::isfinite;
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 58bbdc33920..b767c60c617 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -25,33 +25,34 @@
#include <string.h>
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-
-#include "osl_closures.h"
-#include "osl_globals.h"
-#include "osl_services.h"
-#include "osl_shader.h"
-
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_string.h"
-
-#include "kernel_compat_cpu.h"
-#include "kernel_globals.h"
-#include "kernel_random.h"
-#include "kernel_projection.h"
-#include "kernel_differential.h"
-#include "kernel_montecarlo.h"
-#include "kernel_camera.h"
-#include "kernels/cpu/kernel_cpu_image.h"
-#include "geom/geom.h"
-#include "bvh/bvh.h"
-
-#include "kernel_projection.h"
-#include "kernel_accumulate.h"
-#include "kernel_shader.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+
+#include "kernel/osl/osl_closures.h"
+#include "kernel/osl/osl_globals.h"
+#include "kernel/osl/osl_services.h"
+#include "kernel/osl/osl_shader.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_string.h"
+
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/split/kernel_split_data_types.h"
+#include "kernel/kernel_globals.h"
+#include "kernel/kernel_random.h"
+#include "kernel/kernel_projection.h"
+#include "kernel/kernel_differential.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/kernel_camera.h"
+#include "kernel/kernels/cpu/kernel_cpu_image.h"
+#include "kernel/geom/geom.h"
+#include "kernel/bvh/bvh.h"
+
+#include "kernel/kernel_projection.h"
+#include "kernel/kernel_accumulate.h"
+#include "kernel/kernel_shader.h"
#ifdef WITH_PTEX
# include <Ptexture.h>
diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp
index 0d762bbdb38..13b19d86eca 100644
--- a/intern/cycles/kernel/osl/osl_shader.cpp
+++ b/intern/cycles/kernel/osl/osl_shader.cpp
@@ -16,21 +16,22 @@
#include <OSL/oslexec.h>
-#include "kernel_compat_cpu.h"
-#include "kernel_montecarlo.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
+#include "kernel/kernel_compat_cpu.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/kernel_types.h"
+#include "kernel/split/kernel_split_data_types.h"
+#include "kernel/kernel_globals.h"
-#include "geom/geom_object.h"
+#include "kernel/geom/geom_object.h"
-#include "osl_closures.h"
-#include "osl_globals.h"
-#include "osl_services.h"
-#include "osl_shader.h"
+#include "kernel/osl/osl_closures.h"
+#include "kernel/osl/osl_globals.h"
+#include "kernel/osl/osl_services.h"
+#include "kernel/osl/osl_shader.h"
-#include "util_foreach.h"
+#include "util/util_foreach.h"
-#include "attribute.h"
+#include "render/attribute.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h
index ad06dd6929d..32121e940b4 100644
--- a/intern/cycles/kernel/osl/osl_shader.h
+++ b/intern/cycles/kernel/osl/osl_shader.h
@@ -29,7 +29,7 @@
* This means no thread state must be passed along in the kernel itself.
*/
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/split/kernel_background_buffer_update.h b/intern/cycles/kernel/split/kernel_background_buffer_update.h
deleted file mode 100644
index 9bfa71c75ef..00000000000
--- a/intern/cycles/kernel/split/kernel_background_buffer_update.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2011-2015 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 "kernel_split_common.h"
-
-/* Note on kernel_background_buffer_update kernel.
- * This is the fourth kernel in the ray tracing logic, and the third
- * of the path iteration kernels. This kernel takes care of rays that hit
- * the background (sceneintersect kernel), and for the rays of
- * state RAY_UPDATE_BUFFER it updates the ray's accumulated radiance in
- * the output buffer. This kernel also takes care of rays that have been determined
- * to-be-regenerated.
- *
- * We will empty QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue in this kernel
- *
- * Typically all rays that are in state RAY_HIT_BACKGROUND, RAY_UPDATE_BUFFER
- * will be eventually set to RAY_TO_REGENERATE state in this kernel. Finally all rays of ray_state
- * RAY_TO_REGENERATE will be regenerated and put in queue QUEUE_ACTIVE_AND_REGENERATED_RAYS.
- *
- * The input and output are as follows,
- *
- * rng_coop ---------------------------------------------|--- kernel_background_buffer_update --|--- PathRadiance_coop
- * throughput_coop --------------------------------------| |--- L_transparent_coop
- * per_sample_output_buffers ----------------------------| |--- per_sample_output_buffers
- * Ray_coop ---------------------------------------------| |--- ray_state
- * PathState_coop ---------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * L_transparent_coop -----------------------------------| |--- Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS)
- * ray_state --------------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ----| |--- Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS)
- * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ------| |--- work_array
- * parallel_samples -------------------------------------| |--- PathState_coop
- * end_sample -------------------------------------------| |--- throughput_coop
- * kg (globals) -----------------------------------------| |--- rng_coop
- * rng_state --------------------------------------------| |--- Ray
- * PathRadiance_coop ------------------------------------| |
- * sw ---------------------------------------------------| |
- * sh ---------------------------------------------------| |
- * sx ---------------------------------------------------| |
- * sy ---------------------------------------------------| |
- * stride -----------------------------------------------| |
- * work_array -------------------------------------------| |--- work_array
- * queuesize --------------------------------------------| |
- * start_sample -----------------------------------------| |--- work_pool_wgs
- * work_pool_wgs ----------------------------------------| |
- * num_samples ------------------------------------------| |
- *
- * note on sd : sd argument is neither an input nor an output for this kernel. It is just filled and consumed here itself.
- * Note on Queues :
- * This kernel fetches rays from QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
- *
- * State of queues when this kernel is called :
- * At entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND, RAY_TO_REGENERATE rays
- * At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty
- */
-ccl_device char kernel_background_buffer_update(
- KernelGlobals *kg,
- ccl_global float *per_sample_output_buffers,
- ccl_global uint *rng_state,
- ccl_global uint *rng_coop, /* Required for buffer Update */
- ccl_global float3 *throughput_coop, /* Required for background hit processing */
- PathRadiance *PathRadiance_coop, /* Required for background hit processing and buffer Update */
- ccl_global Ray *Ray_coop, /* Required for background hit processing */
- ccl_global PathState *PathState_coop, /* Required for background hit processing */
- ccl_global float *L_transparent_coop, /* Required for background hit processing and buffer Update */
- ccl_global char *ray_state, /* Stores information on the current state of a ray */
- int sw, int sh, int sx, int sy, int stride,
- int rng_state_offset_x,
- int rng_state_offset_y,
- int rng_state_stride,
- ccl_global unsigned int *work_array, /* Denotes work of each ray */
- int end_sample,
- int start_sample,
-#ifdef __WORK_STEALING__
- ccl_global unsigned int *work_pool_wgs,
- unsigned int num_samples,
-#endif
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int parallel_samples, /* Number of samples to be processed in parallel */
- int ray_index)
-{
- char enqueue_flag = 0;
-#ifdef __KERNEL_DEBUG__
- DebugData *debug_data = &debugdata_coop[ray_index];
-#endif
- ccl_global PathState *state = &PathState_coop[ray_index];
- PathRadiance *L = L = &PathRadiance_coop[ray_index];
- ccl_global Ray *ray = &Ray_coop[ray_index];
- ccl_global float3 *throughput = &throughput_coop[ray_index];
- ccl_global float *L_transparent = &L_transparent_coop[ray_index];
- ccl_global uint *rng = &rng_coop[ray_index];
-
-#ifdef __WORK_STEALING__
- unsigned int my_work;
- ccl_global float *initial_per_sample_output_buffers;
- ccl_global uint *initial_rng;
-#endif
- unsigned int sample;
- unsigned int tile_x;
- unsigned int tile_y;
- unsigned int pixel_x;
- unsigned int pixel_y;
- unsigned int my_sample_tile;
-
-#ifdef __WORK_STEALING__
- my_work = work_array[ray_index];
- sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
- get_pixel_tile_position(&pixel_x, &pixel_y,
- &tile_x, &tile_y,
- my_work,
- sw, sh, sx, sy,
- parallel_samples,
- ray_index);
- my_sample_tile = 0;
- initial_per_sample_output_buffers = per_sample_output_buffers;
- initial_rng = rng_state;
-#else /* __WORK_STEALING__ */
- sample = work_array[ray_index];
- int tile_index = ray_index / parallel_samples;
- /* buffer and rng_state's stride is "stride". Find x and y using ray_index */
- tile_x = tile_index % sw;
- tile_y = tile_index / sw;
- my_sample_tile = ray_index - (tile_index * parallel_samples);
-#endif /* __WORK_STEALING__ */
-
- rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride;
- per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride;
-
- if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
- /* eval background shader if nothing hit */
- if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
- *L_transparent = (*L_transparent) + average((*throughput));
-#ifdef __PASSES__
- if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
-#endif
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
-#ifdef __BACKGROUND__
- /* sample background shader */
- float3 L_background = indirect_background(kg, kg->sd_input, state, ray);
- path_radiance_accum_background(L, (*throughput), L_background, state->bounce);
-#endif
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- }
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
- float3 L_sum = path_radiance_clamp_and_sum(kg, L);
- kernel_write_light_passes(kg, per_sample_output_buffers, L, sample);
-#ifdef __KERNEL_DEBUG__
- kernel_write_debug_passes(kg, per_sample_output_buffers, state, debug_data, sample);
-#endif
- float4 L_rad = make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - (*L_transparent));
-
- /* accumulate result in output buffer */
- kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad);
- path_rng_end(kg, rng_state, *rng);
-
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
- }
-
- if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
-#ifdef __WORK_STEALING__
- /* We have completed current work; So get next work */
- int valid_work = get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index);
- if(!valid_work) {
- /* If work is invalid, this means no more work is available and the thread may exit */
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
- }
-#else /* __WORK_STEALING__ */
- if((sample + parallel_samples) >= end_sample) {
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
- }
-#endif /* __WORK_STEALING__ */
-
- if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
-#ifdef __WORK_STEALING__
- work_array[ray_index] = my_work;
- /* Get the sample associated with the current work */
- sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
- /* Get pixel and tile position associated with current work */
- get_pixel_tile_position(&pixel_x, &pixel_y, &tile_x, &tile_y, my_work, sw, sh, sx, sy, parallel_samples, ray_index);
- my_sample_tile = 0;
-
- /* Remap rng_state according to the current work */
- rng_state = initial_rng + ((rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride);
- /* Remap per_sample_output_buffers according to the current work */
- per_sample_output_buffers = initial_per_sample_output_buffers
- + (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) * kernel_data.film.pass_stride;
-#else /* __WORK_STEALING__ */
- work_array[ray_index] = sample + parallel_samples;
- sample = work_array[ray_index];
-
- /* Get ray position from ray index */
- pixel_x = sx + ((ray_index / parallel_samples) % sw);
- pixel_y = sy + ((ray_index / parallel_samples) / sw);
-#endif /* __WORK_STEALING__ */
-
- /* Initialize random numbers and ray. */
- kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, rng, ray);
-
- if(ray->t != 0.0f) {
- /* Initialize throughput, L_transparent, Ray, PathState;
- * These rays proceed with path-iteration.
- */
- *throughput = make_float3(1.0f, 1.0f, 1.0f);
- *L_transparent = 0.0f;
- path_radiance_init(L, kernel_data.film.use_light_pass);
- path_state_init(kg, kg->sd_input, state, rng, sample, ray);
-#ifdef __KERNEL_DEBUG__
- debug_data_init(debug_data);
-#endif
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
- enqueue_flag = 1;
- }
- else {
- /* These rays do not participate in path-iteration. */
- float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- /* Accumulate result in output buffer. */
- kernel_write_pass_float4(per_sample_output_buffers, sample, L_rad);
- path_rng_end(kg, rng_state, *rng);
-
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
- }
- }
- }
- return enqueue_flag;
-}
diff --git a/intern/cycles/kernel/split/kernel_buffer_update.h b/intern/cycles/kernel/split/kernel_buffer_update.h
new file mode 100644
index 00000000000..859c221d976
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_buffer_update.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2011-2015 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* This kernel takes care of rays that hit the background (sceneintersect
+ * kernel), and for the rays of state RAY_UPDATE_BUFFER it updates the ray's
+ * accumulated radiance in the output buffer. This kernel also takes care of
+ * rays that have been determined to-be-regenerated.
+ *
+ * We will empty QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue in this kernel.
+ *
+ * Typically all rays that are in state RAY_HIT_BACKGROUND, RAY_UPDATE_BUFFER
+ * will be eventually set to RAY_TO_REGENERATE state in this kernel.
+ * Finally all rays of ray_state RAY_TO_REGENERATE will be regenerated and put
+ * in queue QUEUE_ACTIVE_AND_REGENERATED_RAYS.
+ *
+ * State of queues when this kernel is called:
+ * At entry,
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND, RAY_TO_REGENERATE rays.
+ * At exit,
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and
+ * RAY_REGENERATED rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.
+ */
+ccl_device void kernel_buffer_update(KernelGlobals *kg,
+ ccl_local_param unsigned int *local_queue_atomics)
+{
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(ray_index == 0) {
+ /* We will empty this queue in this kernel. */
+ kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
+ }
+ char enqueue_flag = 0;
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+
+ ccl_global uint *rng_state = kernel_split_params.rng_state;
+ int stride = kernel_split_params.stride;
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+#ifdef __KERNEL_DEBUG__
+ DebugData *debug_data = &kernel_split_state.debug_data[ray_index];
+#endif
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
+ ccl_global float *buffer = kernel_split_params.buffer;
+
+ unsigned int work_index;
+ ccl_global uint *initial_rng;
+
+ unsigned int sample;
+ unsigned int tile_x;
+ unsigned int tile_y;
+ unsigned int pixel_x;
+ unsigned int pixel_y;
+
+ work_index = kernel_split_state.work_array[ray_index];
+ sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+ get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
+ &tile_x, &tile_y,
+ work_index,
+ ray_index);
+ initial_rng = rng_state;
+
+ rng_state += kernel_split_params.offset + pixel_x + pixel_y*stride;
+ buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
+
+ if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ float3 L_sum;
+#ifdef __SHADOW_TRICKS__
+ if(state->flag & PATH_RAY_SHADOW_CATCHER) {
+ L_sum = path_radiance_sum_shadowcatcher(kg, L, L_transparent);
+ }
+ else
+#endif /* __SHADOW_TRICKS__ */
+ {
+ L_sum = path_radiance_clamp_and_sum(kg, L);
+ }
+ kernel_write_light_passes(kg, buffer, L, sample);
+#ifdef __KERNEL_DEBUG__
+ kernel_write_debug_passes(kg, buffer, state, debug_data, sample);
+#endif
+ float4 L_rad = make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - (*L_transparent));
+
+ /* accumulate result in output buffer */
+ kernel_write_pass_float4(buffer, sample, L_rad);
+ path_rng_end(kg, rng_state, rng);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+ /* We have completed current work; So get next work */
+ int valid_work = get_next_work(kg, &work_index, ray_index);
+ if(!valid_work) {
+ /* If work is invalid, this means no more work is available and the thread may exit */
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_INACTIVE);
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_TO_REGENERATE)) {
+ kernel_split_state.work_array[ray_index] = work_index;
+ /* Get the sample associated with the current work */
+ sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+ /* Get pixel and tile position associated with current work */
+ get_work_pixel_tile_position(kg, &pixel_x, &pixel_y, &tile_x, &tile_y, work_index, ray_index);
+
+ /* Remap rng_state according to the current work */
+ rng_state = initial_rng + kernel_split_params.offset + pixel_x + pixel_y*stride;
+ /* Remap buffer according to the current work */
+ buffer += (kernel_split_params.offset + pixel_x + pixel_y*stride) * kernel_data.film.pass_stride;
+
+ /* Initialize random numbers and ray. */
+ kernel_path_trace_setup(kg, rng_state, sample, pixel_x, pixel_y, &rng, ray);
+
+ if(ray->t != 0.0f) {
+ /* Initialize throughput, L_transparent, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ *throughput = make_float3(1.0f, 1.0f, 1.0f);
+ *L_transparent = 0.0f;
+ path_radiance_init(L, kernel_data.film.use_light_pass);
+ path_state_init(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &rng, sample, ray);
+#ifdef __SUBSURFACE__
+ kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
+#endif
+#ifdef __KERNEL_DEBUG__
+ debug_data_init(debug_data);
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ enqueue_flag = 1;
+ }
+ else {
+ /* These rays do not participate in path-iteration. */
+ float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ /* Accumulate result in output buffer. */
+ kernel_write_pass_float4(buffer, sample, L_rad);
+ path_rng_end(kg, rng_state, rng);
+
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+ }
+ }
+ kernel_split_state.rng[ray_index] = rng;
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_REGENERATED rays into QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ * These rays will be made active during next SceneIntersectkernel.
+ */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_data_init.h b/intern/cycles/kernel/split/kernel_data_init.h
index 6e158d53d23..9d3d01fff75 100644
--- a/intern/cycles/kernel/split/kernel_data_init.h
+++ b/intern/cycles/kernel/split/kernel_data_init.h
@@ -14,108 +14,105 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_data_initialization kernel
- * This kernel Initializes structures needed in path-iteration kernels.
- * This is the first kernel in ray-tracing logic.
+/* This kernel Initializes structures needed in path-iteration kernels.
*
- * Ray state of rays outside the tile-boundary will be marked RAY_INACTIVE
- *
- * Its input and output are as follows,
- *
- * Un-initialized rng---------------|--- kernel_data_initialization ---|--- Initialized rng
- * Un-initialized throughput -------| |--- Initialized throughput
- * Un-initialized L_transparent ----| |--- Initialized L_transparent
- * Un-initialized PathRadiance -----| |--- Initialized PathRadiance
- * Un-initialized Ray --------------| |--- Initialized Ray
- * Un-initialized PathState --------| |--- Initialized PathState
- * Un-initialized QueueData --------| |--- Initialized QueueData (to QUEUE_EMPTY_SLOT)
- * Un-initialized QueueIndex -------| |--- Initialized QueueIndex (to 0)
- * Un-initialized use_queues_flag---| |--- Initialized use_queues_flag (to false)
- * Un-initialized ray_state --------| |--- Initialized ray_state
- * parallel_samples --------------- | |--- Initialized per_sample_output_buffers
- * rng_state -----------------------| |--- Initialized work_array
- * data ----------------------------| |--- Initialized work_pool_wgs
- * start_sample --------------------| |
- * sx ------------------------------| |
- * sy ------------------------------| |
- * sw ------------------------------| |
- * sh ------------------------------| |
- * stride --------------------------| |
- * queuesize -----------------------| |
- * num_samples ---------------------| |
- *
- * Note on Queues :
+ * Note on Queues:
* All slots in queues are initialized to queue empty slot;
* The number of elements in the queues is initialized to 0;
*/
+
+/* Distributes an amount of work across all threads
+ * note: work done inside the loop may not show up to all threads till after
+ * the current kernel has completed
+ */
+#define parallel_for(kg, iter_name, work_size) \
+ for(size_t _size = (work_size), \
+ _global_size = ccl_global_size(0) * ccl_global_size(1), \
+ _n = _size / _global_size, \
+ _thread = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0), \
+ iter_name = (_n > 0) ? (_thread * _n) : (_thread) \
+ ; \
+ (iter_name < (_thread+1) * _n) || (iter_name == _n * _global_size + _thread && _thread < _size % _global_size) \
+ ; \
+ iter_name = (iter_name != (_thread+1) * _n - 1) ? (iter_name + 1) : (_n * _global_size + _thread) \
+ )
+
+#ifndef __KERNEL_CPU__
ccl_device void kernel_data_init(
+#else
+void KERNEL_FUNCTION_FULL_NAME(data_init)(
+#endif
KernelGlobals *kg,
- ShaderData *sd_DL_shadow,
ccl_constant KernelData *data,
- ccl_global float *per_sample_output_buffers,
+ ccl_global void *split_data_buffer,
+ int num_elements,
+ ccl_global char *ray_state,
ccl_global uint *rng_state,
- ccl_global uint *rng_coop, /* rng array to store rng values for all rays */
- ccl_global float3 *throughput_coop, /* throughput array to store throughput values for all rays */
- ccl_global float *L_transparent_coop, /* L_transparent array to store L_transparent values for all rays */
- PathRadiance *PathRadiance_coop, /* PathRadiance array to store PathRadiance values for all rays */
- ccl_global Ray *Ray_coop, /* Ray array to store Ray information for all rays */
- ccl_global PathState *PathState_coop, /* PathState array to store PathState information for all rays */
- Intersection *Intersection_coop_shadow,
- ccl_global char *ray_state, /* Stores information on current state of a ray */
+#ifdef __KERNEL_OPENCL__
#define KERNEL_TEX(type, ttype, name) \
ccl_global type *name,
-#include "../kernel_textures.h"
+#include "kernel/kernel_textures.h"
+#endif
- int start_sample, int sx, int sy, int sw, int sh, int offset, int stride,
- int rng_state_offset_x,
- int rng_state_offset_y,
- int rng_state_stride,
- ccl_global int *Queue_data, /* Memory for queues */
+ int start_sample,
+ int end_sample,
+ int sx, int sy, int sw, int sh, int offset, int stride,
ccl_global int *Queue_index, /* Tracks the number of elements in queues */
int queuesize, /* size (capacity) of the queue */
ccl_global char *use_queues_flag, /* flag to decide if scene-intersect kernel should use queues to fetch ray index */
- ccl_global unsigned int *work_array, /* work array to store which work each ray belongs to */
-#ifdef __WORK_STEALING__
- ccl_global unsigned int *work_pool_wgs, /* Work pool for each work group */
- unsigned int num_samples, /* Total number of samples per pixel */
-#endif
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int parallel_samples) /* Number of samples to be processed in parallel */
+ ccl_global unsigned int *work_pools, /* Work pool for each work group */
+ unsigned int num_samples,
+ ccl_global float *buffer)
{
+#ifdef __KERNEL_OPENCL__
kg->data = data;
- kg->sd_input = sd_DL_shadow;
- kg->isect_shadow = Intersection_coop_shadow;
+#endif
+
+ kernel_split_params.x = sx;
+ kernel_split_params.y = sy;
+ kernel_split_params.w = sw;
+ kernel_split_params.h = sh;
+
+ kernel_split_params.offset = offset;
+ kernel_split_params.stride = stride;
+
+ kernel_split_params.rng_state = rng_state;
+
+ kernel_split_params.start_sample = start_sample;
+ kernel_split_params.end_sample = end_sample;
+
+ kernel_split_params.work_pools = work_pools;
+ kernel_split_params.num_samples = num_samples;
+
+ kernel_split_params.queue_index = Queue_index;
+ kernel_split_params.queue_size = queuesize;
+ kernel_split_params.use_queues_flag = use_queues_flag;
+
+ kernel_split_params.buffer = buffer;
+
+ split_data_init(kg, &kernel_split_state, num_elements, split_data_buffer, ray_state);
+
+#ifdef __KERNEL_OPENCL__
#define KERNEL_TEX(type, ttype, name) \
kg->name = name;
-#include "../kernel_textures.h"
-
- int thread_index = get_global_id(1) * get_global_size(0) + get_global_id(0);
+#include "kernel/kernel_textures.h"
+#endif
-#ifdef __WORK_STEALING__
- int lid = get_local_id(1) * get_local_size(0) + get_local_id(0);
- /* Initialize work_pool_wgs */
- if(lid == 0) {
- int group_index = get_group_id(1) * get_num_groups(0) + get_group_id(0);
- work_pool_wgs[group_index] = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-#endif /* __WORK_STEALING__ */
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
/* Initialize queue data and queue index. */
if(thread_index < queuesize) {
/* Initialize active ray queue. */
- Queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ kernel_split_state.queue_data[QUEUE_ACTIVE_AND_REGENERATED_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
/* Initialize background and buffer update queue. */
- Queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ kernel_split_state.queue_data[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
/* Initialize shadow ray cast of AO queue. */
- Queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_AO_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
/* Initialize shadow ray cast of direct lighting queue. */
- Queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
+ kernel_split_state.queue_data[QUEUE_SHADOW_RAY_CAST_DL_RAYS * queuesize + thread_index] = QUEUE_EMPTY_SLOT;
}
if(thread_index == 0) {
@@ -126,109 +123,31 @@ ccl_device void kernel_data_init(
/* The scene-intersect kernel should not use the queues very first time.
* since the queue would be empty.
*/
- use_queues_flag[0] = 0;
+ *use_queues_flag = 0;
}
- int x = get_global_id(0);
- int y = get_global_id(1);
+ /* zero the tiles pixels and initialize rng_state if this is the first sample */
+ if(start_sample == 0) {
+ parallel_for(kg, i, sw * sh * kernel_data.film.pass_stride) {
+ int pixel = i / kernel_data.film.pass_stride;
+ int pass = i % kernel_data.film.pass_stride;
- if(x < (sw * parallel_samples) && y < sh) {
- int ray_index = x + y * (sw * parallel_samples);
+ int x = sx + pixel % sw;
+ int y = sy + pixel / sw;
- /* This is the first assignment to ray_state;
- * So we dont use ASSIGN_RAY_STATE macro.
- */
- ray_state[ray_index] = RAY_ACTIVE;
-
- unsigned int my_sample;
- unsigned int pixel_x;
- unsigned int pixel_y;
- unsigned int tile_x;
- unsigned int tile_y;
- unsigned int my_sample_tile;
-
-#ifdef __WORK_STEALING__
- unsigned int my_work = 0;
- /* Get work. */
- get_next_work(work_pool_wgs, &my_work, sw, sh, num_samples, parallel_samples, ray_index);
- /* Get the sample associated with the work. */
- my_sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
-
- my_sample_tile = 0;
-
- /* Get pixel and tile position associated with the work. */
- get_pixel_tile_position(&pixel_x, &pixel_y,
- &tile_x, &tile_y,
- my_work,
- sw, sh, sx, sy,
- parallel_samples,
- ray_index);
- work_array[ray_index] = my_work;
-#else /* __WORK_STEALING__ */
- unsigned int tile_index = ray_index / parallel_samples;
- tile_x = tile_index % sw;
- tile_y = tile_index / sw;
- my_sample_tile = ray_index - (tile_index * parallel_samples);
- my_sample = my_sample_tile + start_sample;
-
- /* Initialize work array. */
- work_array[ray_index] = my_sample ;
-
- /* Calculate pixel position of this ray. */
- pixel_x = sx + tile_x;
- pixel_y = sy + tile_y;
-#endif /* __WORK_STEALING__ */
-
- rng_state += (rng_state_offset_x + tile_x) + (rng_state_offset_y + tile_y) * rng_state_stride;
-
- /* Initialise per_sample_output_buffers to all zeros. */
- per_sample_output_buffers += (((tile_x + (tile_y * stride)) * parallel_samples) + (my_sample_tile)) * kernel_data.film.pass_stride;
- int per_sample_output_buffers_iterator = 0;
- for(per_sample_output_buffers_iterator = 0;
- per_sample_output_buffers_iterator < kernel_data.film.pass_stride;
- per_sample_output_buffers_iterator++)
- {
- per_sample_output_buffers[per_sample_output_buffers_iterator] = 0.0f;
- }
+ int index = (offset + x + y*stride) * kernel_data.film.pass_stride + pass;
- /* Initialize random numbers and ray. */
- kernel_path_trace_setup(kg,
- rng_state,
- my_sample,
- pixel_x, pixel_y,
- &rng_coop[ray_index],
- &Ray_coop[ray_index]);
-
- if(Ray_coop[ray_index].t != 0.0f) {
- /* Initialize throughput, L_transparent, Ray, PathState;
- * These rays proceed with path-iteration.
- */
- throughput_coop[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
- L_transparent_coop[ray_index] = 0.0f;
- path_radiance_init(&PathRadiance_coop[ray_index], kernel_data.film.use_light_pass);
- path_state_init(kg,
- kg->sd_input,
- &PathState_coop[ray_index],
- &rng_coop[ray_index],
- my_sample,
- &Ray_coop[ray_index]);
-#ifdef __KERNEL_DEBUG__
- debug_data_init(&debugdata_coop[ray_index]);
-#endif
+ *(buffer + index) = 0.0f;
}
- else {
- /* These rays do not participate in path-iteration. */
- float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
- /* Accumulate result in output buffer. */
- kernel_write_pass_float4(per_sample_output_buffers, my_sample, L_rad);
- path_rng_end(kg, rng_state, rng_coop[ray_index]);
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_TO_REGENERATE);
- }
- }
- /* Mark rest of the ray-state indices as RAY_INACTIVE. */
- if(thread_index < (get_global_size(0) * get_global_size(1)) - (sh * (sw * parallel_samples))) {
- /* First assignment, hence we dont use ASSIGN_RAY_STATE macro */
- ray_state[((sw * parallel_samples) * sh) + thread_index] = RAY_INACTIVE;
+ parallel_for(kg, i, sw * sh) {
+ int x = sx + i % sw;
+ int y = sy + i / sw;
+
+ int index = (offset + x + y*stride);
+ *(rng_state + index) = hash_int_2d(x, y);
+ }
}
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_direct_lighting.h b/intern/cycles/kernel/split/kernel_direct_lighting.h
index 82ca18829d3..bdbf7387b95 100644
--- a/intern/cycles/kernel/split/kernel_direct_lighting.h
+++ b/intern/cycles/kernel/split/kernel_direct_lighting.h
@@ -14,95 +14,144 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_direct_lighting kernel.
- * This is the eighth kernel in the ray tracing logic. This is the seventh
- * of the path iteration kernels. This kernel takes care of direct lighting
- * logic. However, the "shadow ray cast" part of direct lighting is handled
+/* This kernel takes care of direct lighting logic.
+ * However, the "shadow ray cast" part of direct lighting is handled
* in the next kernel.
*
- * This kernels determines the rays for which a shadow_blocked() function associated with direct lighting should be executed.
- * Those rays for which a shadow_blocked() function for direct-lighting must be executed, are marked with flag RAY_SHADOW_RAY_CAST_DL and
- * enqueued into the queue QUEUE_SHADOW_RAY_CAST_DL_RAYS
+ * This kernels determines the rays for which a shadow_blocked() function
+ * associated with direct lighting should be executed. Those rays for which
+ * a shadow_blocked() function for direct-lighting must be executed, are
+ * marked with flag RAY_SHADOW_RAY_CAST_DL and enqueued into the queue
+ * QUEUE_SHADOW_RAY_CAST_DL_RAYS
*
- * The input and output are as follows,
+ * Note on Queues:
+ * This kernel only reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue
+ * and processes only the rays of state RAY_ACTIVE; If a ray needs to execute
+ * the corresponding shadow_blocked part, after direct lighting, the ray is
+ * marked with RAY_SHADOW_RAY_CAST_DL flag.
*
- * rng_coop -----------------------------------------|--- kernel_direct_lighting --|--- BSDFEval_coop
- * PathState_coop -----------------------------------| |--- ISLamp_coop
- * sd -----------------------------------------------| |--- LightRay_coop
- * ray_state ----------------------------------------| |--- ray_state
- * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| |
- * kg (globals) -------------------------------------| |
- * queuesize ----------------------------------------| |
- *
- * Note on Queues :
- * This kernel only reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes
- * only the rays of state RAY_ACTIVE; If a ray needs to execute the corresponding shadow_blocked
- * part, after direct lighting, the ray is marked with RAY_SHADOW_RAY_CAST_DL flag.
- *
- * State of queues when this kernel is called :
- * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same
- * before and after this kernel call.
- * QUEUE_SHADOW_RAY_CAST_DL_RAYS queue will be filled with rays for which a shadow_blocked function must be executed, after this
- * kernel call. Before this kernel call the QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty.
+ * State of queues when this kernel is called:
+ * - State of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same before and after this
+ * kernel call.
+ * - QUEUE_SHADOW_RAY_CAST_DL_RAYS queue will be filled with rays for which a
+ * shadow_blocked function must be executed, after this kernel call
+ * Before this kernel call the QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty.
*/
-ccl_device char kernel_direct_lighting(
- KernelGlobals *kg,
- ShaderData *sd, /* Required for direct lighting */
- ccl_global uint *rng_coop, /* Required for direct lighting */
- ccl_global PathState *PathState_coop, /* Required for direct lighting */
- ccl_global int *ISLamp_coop, /* Required for direct lighting */
- ccl_global Ray *LightRay_coop, /* Required for direct lighting */
- ccl_global BsdfEval *BSDFEval_coop, /* Required for direct lighting */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int ray_index)
+ccl_device void kernel_direct_lighting(KernelGlobals *kg,
+ ccl_local_param unsigned int *local_queue_atomics)
{
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
char enqueue_flag = 0;
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- ccl_global PathState *state = &PathState_coop[ray_index];
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ ShaderData *sd = &kernel_split_state.sd[ray_index];
/* direct lighting */
#ifdef __EMISSION__
- if((kernel_data.integrator.use_direct_light &&
- (ccl_fetch(sd, flag) & SD_BSDF_HAS_EVAL)))
- {
+ RNG rng = kernel_split_state.rng[ray_index];
+ bool flag = (kernel_data.integrator.use_direct_light &&
+ (sd->flag & SD_BSDF_HAS_EVAL));
+# ifdef __SHADOW_TRICKS__
+ if(flag && state->flag & PATH_RAY_SHADOW_CATCHER) {
+ flag = false;
+ ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
+ float3 throughput = kernel_split_state.throughput[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ kernel_branched_path_surface_connect_light(kg,
+ &rng,
+ sd,
+ emission_sd,
+ state,
+ throughput,
+ 1.0f,
+ L,
+ 1);
+ }
+# endif /* __SHADOW_TRICKS__ */
+ if(flag) {
/* Sample illumination from lights to find path contribution. */
- ccl_global RNG* rng = &rng_coop[ray_index];
- float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, &rng, state, PRNG_LIGHT);
float light_u, light_v;
- path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
- float terminate = path_state_rng_light_termination(kg, rng, state);
+ path_state_rng_2D(kg, &rng, state, PRNG_LIGHT_U, &light_u, &light_v);
+ float terminate = path_state_rng_light_termination(kg, &rng, state);
LightSample ls;
if(light_sample(kg,
light_t, light_u, light_v,
- ccl_fetch(sd, time),
- ccl_fetch(sd, P),
+ sd->time,
+ sd->P,
state->bounce,
&ls)) {
Ray light_ray;
-#ifdef __OBJECT_MOTION__
- light_ray.time = ccl_fetch(sd, time);
-#endif
+# ifdef __OBJECT_MOTION__
+ light_ray.time = sd->time;
+# endif
BsdfEval L_light;
bool is_lamp;
- if(direct_emission(kg, sd, kg->sd_input, &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
+ if(direct_emission(kg, sd, &kernel_split_state.sd_DL_shadow[ray_index], &ls, state, &light_ray, &L_light, &is_lamp, terminate)) {
/* Write intermediate data to global memory to access from
* the next kernel.
*/
- LightRay_coop[ray_index] = light_ray;
- BSDFEval_coop[ray_index] = L_light;
- ISLamp_coop[ray_index] = is_lamp;
+ kernel_split_state.light_ray[ray_index] = light_ray;
+ kernel_split_state.bsdf_eval[ray_index] = L_light;
+ kernel_split_state.is_lamp[ray_index] = is_lamp;
/* Mark ray state for next shadow kernel. */
- ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
+ ADD_RAY_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
enqueue_flag = 1;
}
}
}
+ kernel_split_state.rng[ray_index] = rng;
#endif /* __EMISSION__ */
}
- return enqueue_flag;
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+#ifdef __EMISSION__
+ /* Enqueue RAY_SHADOW_RAY_CAST_DL rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_DL_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+#endif
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_do_volume.h b/intern/cycles/kernel/split/kernel_do_volume.h
new file mode 100644
index 00000000000..47d3c280831
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_do_volume.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+
+ccl_device void kernel_do_volume(KernelGlobals *kg)
+{
+#ifdef __VOLUME__
+ /* We will empty this queue in this kernel. */
+ if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
+ }
+ /* Fetch use_queues_flag. */
+ char local_use_queues_flag = *kernel_split_params.use_queues_flag;
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(local_use_queues_flag) {
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ }
+
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+
+ bool hit = ! IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND);
+
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
+ ccl_global Intersection *isect = &kernel_split_state.isect[ray_index];
+ ShaderData *sd = &kernel_split_state.sd[ray_index];
+ ShaderData *sd_input = &kernel_split_state.sd_DL_shadow[ray_index];
+
+ /* Sanitize volume stack. */
+ if(!hit) {
+ kernel_volume_clean_stack(kg, state->volume_stack);
+ }
+ /* volume attenuation, emission, scatter */
+ if(state->volume_stack[0].shader != SHADER_NONE) {
+ Ray volume_ray = *ray;
+ volume_ray.t = (hit)? isect->t: FLT_MAX;
+
+ bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
+
+ {
+ /* integrate along volume segment with distance sampling */
+ VolumeIntegrateResult result = kernel_volume_integrate(
+ kg, state, sd, &volume_ray, L, throughput, &rng, heterogeneous);
+
+# ifdef __VOLUME_SCATTER__
+ if(result == VOLUME_PATH_SCATTERED) {
+ /* direct lighting */
+ kernel_path_volume_connect_light(kg, &rng, sd, sd_input, *throughput, state, L);
+
+ /* indirect light bounce */
+ if(kernel_path_volume_bounce(kg, &rng, sd, throughput, state, L, ray))
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED);
+ else
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+# endif
+ }
+ }
+ kernel_split_state.rng[ray_index] = rng;
+ }
+
+#endif
+}
+
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
index 5d951b972ed..9fc853a84bf 100644
--- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
+++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
@@ -14,157 +14,159 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_holdout_emission_blurring_pathtermination_ao kernel.
- * This is the sixth kernel in the ray tracing logic. This is the fifth
- * of the path iteration kernels. This kernel takes care of the logic to process
- * "material of type holdout", indirect primitive emission, bsdf blurring,
- * probabilistic path termination and AO.
+/* This kernel takes care of the logic to process "material of type holdout",
+ * indirect primitive emission, bsdf blurring, probabilistic path termination
+ * and AO.
*
- * This kernels determines the rays for which a shadow_blocked() function associated with AO should be executed.
- * Those rays for which a shadow_blocked() function for AO must be executed are marked with flag RAY_SHADOW_RAY_CAST_ao and
- * enqueued into the queue QUEUE_SHADOW_RAY_CAST_AO_RAYS
+ * This kernels determines the rays for which a shadow_blocked() function
+ * associated with AO should be executed. Those rays for which a
+ * shadow_blocked() function for AO must be executed are marked with flag
+ * RAY_SHADOW_RAY_CAST_ao and enqueued into the queue
+ * QUEUE_SHADOW_RAY_CAST_AO_RAYS
*
* Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER
*
- * The input and output are as follows,
+ * Note on Queues:
+ * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS
+ * and processes only the rays of state RAY_ACTIVE.
+ * There are different points in this kernel where a ray may terminate and
+ * reach RAY_UPDATE_BUFFER state. These rays are enqueued into
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will still be present
+ * in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has
+ * been changed to RAY_UPDATE_BUFFER, there is no problem.
*
- * rng_coop ---------------------------------------------|--- kernel_holdout_emission_blurring_pathtermination_ao ---|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * throughput_coop --------------------------------------| |--- PathState_coop
- * PathRadiance_coop ------------------------------------| |--- throughput_coop
- * Intersection_coop ------------------------------------| |--- L_transparent_coop
- * PathState_coop ---------------------------------------| |--- per_sample_output_buffers
- * L_transparent_coop -----------------------------------| |--- PathRadiance_coop
- * sd ---------------------------------------------------| |--- ShaderData
- * ray_state --------------------------------------------| |--- ray_state
- * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- AOAlpha_coop
- * kg (globals) -----------------------------------------| |--- AOBSDF_coop
- * parallel_samples -------------------------------------| |--- AOLightRay_coop
- * per_sample_output_buffers ----------------------------| |
- * sw ---------------------------------------------------| |
- * sh ---------------------------------------------------| |
- * sx ---------------------------------------------------| |
- * sy ---------------------------------------------------| |
- * stride -----------------------------------------------| |
- * work_array -------------------------------------------| |
- * queuesize --------------------------------------------| |
- * start_sample -----------------------------------------| |
- *
- * Note on Queues :
- * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only
- * the rays of state RAY_ACTIVE.
- * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFFER
- * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will
- * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been
- * changed to RAY_UPDATE_BUFFER, there is no problem.
- *
- * State of queues when this kernel is called :
+ * State of queues when this kernel is called:
* At entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays.
- * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be empty.
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and
+ * RAY_REGENERATED rays
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_TO_REGENERATE rays.
+ * - QUEUE_SHADOW_RAY_CAST_AO_RAYS will be empty.
* At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and RAY_UPDATE_BUFFER rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays
- * QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with flag RAY_SHADOW_RAY_CAST_AO
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE,
+ * RAY_REGENERATED and RAY_UPDATE_BUFFER rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays.
+ * - QUEUE_SHADOW_RAY_CAST_AO_RAYS will be filled with rays marked with
+ * flag RAY_SHADOW_RAY_CAST_AO
*/
ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
KernelGlobals *kg,
- ShaderData *sd, /* Required throughout the kernel except probabilistic path termination and AO */
- ccl_global float *per_sample_output_buffers,
- ccl_global uint *rng_coop, /* Required for "kernel_write_data_passes" and AO */
- ccl_global float3 *throughput_coop, /* Required for handling holdout material and AO */
- ccl_global float *L_transparent_coop, /* Required for handling holdout material */
- PathRadiance *PathRadiance_coop, /* Required for "kernel_write_data_passes" and indirect primitive emission */
- ccl_global PathState *PathState_coop, /* Required throughout the kernel and AO */
- Intersection *Intersection_coop, /* Required for indirect primitive emission */
- ccl_global float3 *AOAlpha_coop, /* Required for AO */
- ccl_global float3 *AOBSDF_coop, /* Required for AO */
- ccl_global Ray *AOLightRay_coop, /* Required for AO */
- int sw, int sh, int sx, int sy, int stride,
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global unsigned int *work_array, /* Denotes the work that each ray belongs to */
-#ifdef __WORK_STEALING__
- unsigned int start_sample,
-#endif
- int parallel_samples, /* Number of samples to be processed in parallel */
- int ray_index,
- char *enqueue_flag,
- char *enqueue_flag_AO_SHADOW_RAY_CAST)
+ ccl_local_param BackgroundAOLocals *locals)
{
-#ifdef __WORK_STEALING__
- unsigned int my_work;
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ locals->queue_atomics_bg = 0;
+ locals->queue_atomics_ao = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ char enqueue_flag = 0;
+ char enqueue_flag_AO_SHADOW_RAY_CAST = 0;
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif /* __COMPUTE_DEVICE_GPU__ */
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+
+ int stride = kernel_split_params.stride;
+
+ unsigned int work_index;
unsigned int pixel_x;
unsigned int pixel_y;
-#endif
+
unsigned int tile_x;
unsigned int tile_y;
- int my_sample_tile;
unsigned int sample;
- ccl_global RNG *rng = 0x0;
+ RNG rng = kernel_split_state.rng[ray_index];
ccl_global PathState *state = 0x0;
float3 throughput;
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+ ShaderData *sd = &kernel_split_state.sd[ray_index];
+ ccl_global float *buffer = kernel_split_params.buffer;
+
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- throughput = throughput_coop[ray_index];
- state = &PathState_coop[ray_index];
- rng = &rng_coop[ray_index];
-#ifdef __WORK_STEALING__
- my_work = work_array[ray_index];
- sample = get_my_sample(my_work, sw, sh, parallel_samples, ray_index) + start_sample;
- get_pixel_tile_position(&pixel_x, &pixel_y,
+ throughput = kernel_split_state.throughput[ray_index];
+ state = &kernel_split_state.path_state[ray_index];
+
+ work_index = kernel_split_state.work_array[ray_index];
+ sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+ get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
&tile_x, &tile_y,
- my_work,
- sw, sh, sx, sy,
- parallel_samples,
+ work_index,
ray_index);
- my_sample_tile = 0;
-#else /* __WORK_STEALING__ */
- sample = work_array[ray_index];
- /* Buffer's stride is "stride"; Find x and y using ray_index. */
- int tile_index = ray_index / parallel_samples;
- tile_x = tile_index % sw;
- tile_y = tile_index / sw;
- my_sample_tile = ray_index - (tile_index * parallel_samples);
-#endif /* __WORK_STEALING__ */
- per_sample_output_buffers +=
- (((tile_x + (tile_y * stride)) * parallel_samples) + my_sample_tile) *
- kernel_data.film.pass_stride;
+
+ buffer += (kernel_split_params.offset + pixel_x + pixel_y * stride) * kernel_data.film.pass_stride;
+
+#ifdef __SHADOW_TRICKS__
+ if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
+ if (state->flag & PATH_RAY_CAMERA) {
+ state->flag |= (PATH_RAY_SHADOW_CATCHER | PATH_RAY_SHADOW_CATCHER_ONLY);
+ state->catcher_object = sd->object;
+ if(!kernel_data.background.transparent) {
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ L->shadow_color = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
+ }
+ }
+ }
+ else {
+ state->flag &= ~PATH_RAY_SHADOW_CATCHER_ONLY;
+ }
+#endif /* __SHADOW_TRICKS__ */
/* holdout */
#ifdef __HOLDOUT__
- if(((ccl_fetch(sd, flag) & SD_HOLDOUT) ||
- (ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK)) &&
+ if(((sd->flag & SD_HOLDOUT) ||
+ (sd->object_flag & SD_OBJECT_HOLDOUT_MASK)) &&
(state->flag & PATH_RAY_CAMERA))
{
if(kernel_data.background.transparent) {
float3 holdout_weight;
- if(ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK) {
+ if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
holdout_weight = make_float3(1.0f, 1.0f, 1.0f);
}
else {
holdout_weight = shader_holdout_eval(kg, sd);
}
/* any throughput is ok, should all be identical here */
- L_transparent_coop[ray_index] += average(holdout_weight*throughput);
+ kernel_split_state.L_transparent[ray_index] += average(holdout_weight*throughput);
}
- if(ccl_fetch(sd, object_flag) & SD_OBJECT_HOLDOUT_MASK) {
+ if(sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- *enqueue_flag = 1;
+ enqueue_flag = 1;
}
}
#endif /* __HOLDOUT__ */
}
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- PathRadiance *L = &PathRadiance_coop[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
/* Holdout mask objects do not write data passes. */
kernel_write_data_passes(kg,
- per_sample_output_buffers,
+ buffer,
L,
sd,
sample,
@@ -183,12 +185,12 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
#ifdef __EMISSION__
/* emission */
- if(ccl_fetch(sd, flag) & SD_EMISSION) {
+ if(sd->flag & SD_EMISSION) {
/* TODO(sergey): is isect.t wrong here for transparent surfaces? */
float3 emission = indirect_primitive_emission(
kg,
sd,
- Intersection_coop[ray_index].t,
+ kernel_split_state.isect[ray_index].t,
state->flag,
state->ray_pdf);
path_radiance_accum_emission(L, throughput, emission, state->bounce);
@@ -203,18 +205,18 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
if(probability == 0.0f) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- *enqueue_flag = 1;
+ enqueue_flag = 1;
}
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
if(probability != 1.0f) {
- float terminate = path_state_rng_1D_for_decision(kg, rng, state, PRNG_TERMINATE);
+ float terminate = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_TERMINATE);
if(terminate >= probability) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
- *enqueue_flag = 1;
+ enqueue_flag = 1;
}
else {
- throughput_coop[ray_index] = throughput/probability;
+ kernel_split_state.throughput[ray_index] = throughput/probability;
}
}
}
@@ -224,37 +226,65 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion ||
- (ccl_fetch(sd, flag) & SD_AO))
+ (sd->flag & SD_AO))
{
/* todo: solve correlation */
float bsdf_u, bsdf_v;
- path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, &rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
- AOBSDF_coop[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
- AOAlpha_coop[ray_index] = shader_bsdf_alpha(kg, sd);
+ kernel_split_state.ao_bsdf[ray_index] = shader_bsdf_ao(kg, sd, ao_factor, &ao_N);
+ kernel_split_state.ao_alpha[ray_index] = shader_bsdf_alpha(kg, sd);
float3 ao_D;
float ao_pdf;
sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf);
- if(dot(ccl_fetch(sd, Ng), ao_D) > 0.0f && ao_pdf != 0.0f) {
+ if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) {
Ray _ray;
- _ray.P = ray_offset(ccl_fetch(sd, P), ccl_fetch(sd, Ng));
+ _ray.P = ray_offset(sd->P, sd->Ng);
_ray.D = ao_D;
_ray.t = kernel_data.background.ao_distance;
#ifdef __OBJECT_MOTION__
- _ray.time = ccl_fetch(sd, time);
+ _ray.time = sd->time;
#endif
- _ray.dP = ccl_fetch(sd, dP);
+ _ray.dP = sd->dP;
_ray.dD = differential3_zero();
- AOLightRay_coop[ray_index] = _ray;
+ kernel_split_state.ao_light_ray[ray_index] = _ray;
ADD_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
- *enqueue_flag_AO_SHADOW_RAY_CAST = 1;
+ enqueue_flag_AO_SHADOW_RAY_CAST = 1;
}
}
}
#endif /* __AO__ */
+ kernel_split_state.rng[ray_index] = rng;
+
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_UPDATE_BUFFER rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ &locals->queue_atomics_bg,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+
+#ifdef __AO__
+ /* Enqueue to-shadow-ray-cast rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_SHADOW_RAY_CAST_AO_RAYS,
+ enqueue_flag_AO_SHADOW_RAY_CAST,
+ kernel_split_params.queue_size,
+ &locals->queue_atomics_ao,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+#endif
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_indirect_background.h b/intern/cycles/kernel/split/kernel_indirect_background.h
new file mode 100644
index 00000000000..8192528622e
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_indirect_background.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device void kernel_indirect_background(KernelGlobals *kg)
+{
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ int ray_index;
+
+ if(kernel_data.integrator.ao_bounces) {
+ ray_index = get_ray_index(kg, thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ if(state->bounce > kernel_data.integrator.ao_bounces) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+ }
+ }
+ }
+
+ ray_index = get_ray_index(kg, thread_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global float *L_transparent = &kernel_split_state.L_transparent[ray_index];
+
+ if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+ /* eval background shader if nothing hit */
+ if(kernel_data.background.transparent && (state->flag & PATH_RAY_CAMERA)) {
+ *L_transparent = (*L_transparent) + average((*throughput));
+#ifdef __PASSES__
+ if(!(kernel_data.film.pass_flag & PASS_BACKGROUND))
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+
+ if(IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND)) {
+#ifdef __BACKGROUND__
+ /* sample background shader */
+ float3 L_background = indirect_background(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, ray);
+ path_radiance_accum_background(L, state, (*throughput), L_background);
+#endif
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+ }
+
+
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_indirect_subsurface.h b/intern/cycles/kernel/split/kernel_indirect_subsurface.h
new file mode 100644
index 00000000000..a56e85abeb9
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_indirect_subsurface.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device void kernel_indirect_subsurface(KernelGlobals *kg)
+{
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(thread_index == 0) {
+ /* We will empty both queues in this kernel. */
+ kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
+ kernel_split_params.queue_index[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] = 0;
+ }
+
+ int ray_index;
+ get_ray_index(kg, thread_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+ ray_index = get_ray_index(kg, thread_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 1);
+
+#ifdef __SUBSURFACE__
+
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+
+ if(IS_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ ccl_addr_space SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
+ kernel_path_subsurface_accum_indirect(ss_indirect, L);
+
+ /* Trace indirect subsurface rays by restarting the loop. this uses less
+ * stack memory than invoking kernel_path_indirect.
+ */
+ if(ss_indirect->num_rays) {
+ kernel_path_subsurface_setup_indirect(kg,
+ ss_indirect,
+ state,
+ ray,
+ L,
+ throughput);
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_REGENERATED);
+ }
+ else {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ }
+ }
+
+#endif /* __SUBSURFACE__ */
+
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_lamp_emission.h b/intern/cycles/kernel/split/kernel_lamp_emission.h
index 3bd0e361078..c669d79ddcd 100644
--- a/intern/cycles/kernel/split/kernel_lamp_emission.h
+++ b/intern/cycles/kernel/split/kernel_lamp_emission.h
@@ -14,50 +14,49 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_lamp_emission
- * This is the 3rd kernel in the ray-tracing logic. This is the second of the
- * path-iteration kernels. This kernel takes care of the indirect lamp emission logic.
- * This kernel operates on QUEUE_ACTIVE_AND_REGENERATED_RAYS. It processes rays of state RAY_ACTIVE
- * and RAY_HIT_BACKGROUND.
+/* This kernel operates on QUEUE_ACTIVE_AND_REGENERATED_RAYS.
+ * It processes rays of state RAY_ACTIVE and RAY_HIT_BACKGROUND.
* We will empty QUEUE_ACTIVE_AND_REGENERATED_RAYS queue in this kernel.
- * The input/output of the kernel is as follows,
- * Throughput_coop ------------------------------------|--- kernel_lamp_emission --|--- PathRadiance_coop
- * Ray_coop -------------------------------------------| |--- Queue_data(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
- * PathState_coop -------------------------------------| |--- Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
- * kg (globals) ---------------------------------------| |
- * Intersection_coop ----------------------------------| |
- * ray_state ------------------------------------------| |
- * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -----| |
- * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ----| |
- * queuesize ------------------------------------------| |
- * use_queues_flag ------------------------------------| |
- * sw -------------------------------------------------| |
- * sh -------------------------------------------------| |
*/
-ccl_device void kernel_lamp_emission(
- KernelGlobals *kg,
- ccl_global float3 *throughput_coop, /* Required for lamp emission */
- PathRadiance *PathRadiance_coop, /* Required for lamp emission */
- ccl_global Ray *Ray_coop, /* Required for lamp emission */
- ccl_global PathState *PathState_coop, /* Required for lamp emission */
- Intersection *Intersection_coop, /* Required for lamp emission */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int sw, int sh,
- ccl_global char *use_queues_flag, /* Used to decide if this kernel should use
- * queues to fetch ray index
- */
- int ray_index)
+ccl_device void kernel_lamp_emission(KernelGlobals *kg)
{
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
- IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND))
+#ifndef __VOLUME__
+ /* We will empty this queue in this kernel. */
+ if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ kernel_split_params.queue_index[QUEUE_ACTIVE_AND_REGENERATED_RAYS] = 0;
+ }
+#endif
+ /* Fetch use_queues_flag. */
+ char local_use_queues_flag = *kernel_split_params.use_queues_flag;
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(local_use_queues_flag) {
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+#ifndef __VOLUME__
+ 1
+#else
+ 0
+#endif
+ );
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ }
+
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND))
{
- PathRadiance *L = &PathRadiance_coop[ray_index];
- ccl_global PathState *state = &PathState_coop[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
- float3 throughput = throughput_coop[ray_index];
- Ray ray = Ray_coop[ray_index];
+ float3 throughput = kernel_split_state.throughput[ray_index];
+ Ray ray = kernel_split_state.ray[ray_index];
#ifdef __LAMP_MIS__
if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
@@ -65,7 +64,7 @@ ccl_device void kernel_lamp_emission(
Ray light_ray;
light_ray.P = ray.P - state->ray_t*ray.D;
- state->ray_t += Intersection_coop[ray_index].t;
+ state->ray_t += kernel_split_state.isect[ray_index].t;
light_ray.D = ray.D;
light_ray.t = state->ray_t;
light_ray.time = ray.time;
@@ -74,10 +73,13 @@ ccl_device void kernel_lamp_emission(
/* intersect with lamp */
float3 emission;
- if(indirect_lamp_emission(kg, kg->sd_input, state, &light_ray, &emission)) {
+ if(indirect_lamp_emission(kg, &kernel_split_state.sd_DL_shadow[ray_index], state, &light_ray, &emission)) {
path_radiance_accum_emission(L, throughput, emission, state->bounce);
}
}
#endif /* __LAMP_MIS__ */
}
}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/split/kernel_next_iteration_setup.h b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
index 816f3a6fbff..1bebc16e25b 100644
--- a/intern/cycles/kernel/split/kernel_next_iteration_setup.h
+++ b/intern/cycles/kernel/split/kernel_next_iteration_setup.h
@@ -14,128 +14,163 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_setup_next_iteration kernel.
- * This is the tenth kernel in the ray tracing logic. This is the ninth
- * of the path iteration kernels. This kernel takes care of setting up
- * Ray for the next iteration of path-iteration and accumulating radiance
- * corresponding to AO and direct-lighting
+/*This kernel takes care of setting up ray for the next iteration of
+ * path-iteration and accumulating radiance corresponding to AO and
+ * direct-lighting
*
- * Ray state of rays that are terminated in this kernel are changed to RAY_UPDATE_BUFFER
+ * Ray state of rays that are terminated in this kernel are changed
+ * to RAY_UPDATE_BUFFER.
*
- * The input and output are as follows,
+ * Note on queues:
+ * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS
+ * and processes only the rays of state RAY_ACTIVE.
+ * There are different points in this kernel where a ray may terminate and
+ * reach RAY_UPDATE_BUFF state. These rays are enqueued into
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will still be present
+ * in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has
+ * been changed to RAY_UPDATE_BUFF, there is no problem.
*
- * rng_coop ---------------------------------------------|--- kernel_next_iteration_setup -|--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * throughput_coop --------------------------------------| |--- Queue_data (QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS)
- * PathRadiance_coop ------------------------------------| |--- throughput_coop
- * PathState_coop ---------------------------------------| |--- PathRadiance_coop
- * sd ---------------------------------------------------| |--- PathState_coop
- * ray_state --------------------------------------------| |--- ray_state
- * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS) --------| |--- Ray_coop
- * Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS) ---| |--- use_queues_flag
- * Ray_coop ---------------------------------------------| |
- * kg (globals) -----------------------------------------| |
- * LightRay_dl_coop -------------------------------------|
- * ISLamp_coop ------------------------------------------|
- * BSDFEval_coop ----------------------------------------|
- * LightRay_ao_coop -------------------------------------|
- * AOBSDF_coop ------------------------------------------|
- * AOAlpha_coop -----------------------------------------|
- *
- * Note on queues,
- * This kernel fetches rays from the queue QUEUE_ACTIVE_AND_REGENERATED_RAYS and processes only
- * the rays of state RAY_ACTIVE.
- * There are different points in this kernel where a ray may terminate and reach RAY_UPDATE_BUFF
- * state. These rays are enqueued into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. These rays will
- * still be present in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue, but since their ray-state has been
- * changed to RAY_UPDATE_BUFF, there is no problem.
- *
- * State of queues when this kernel is called :
+ * State of queues when this kernel is called:
* At entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED, RAY_UPDATE_BUFFER rays.
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE,
+ * RAY_REGENERATED, RAY_UPDATE_BUFFER rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays.
* At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE, RAY_REGENERATED and more RAY_UPDATE_BUFFER rays.
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE,
+ * RAY_REGENERATED and more RAY_UPDATE_BUFFER rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_TO_REGENERATE and more RAY_UPDATE_BUFFER rays.
*/
-ccl_device char kernel_next_iteration_setup(
- KernelGlobals *kg,
- ShaderData *sd, /* Required for setting up ray for next iteration */
- ccl_global uint *rng_coop, /* Required for setting up ray for next iteration */
- ccl_global float3 *throughput_coop, /* Required for setting up ray for next iteration */
- PathRadiance *PathRadiance_coop, /* Required for setting up ray for next iteration */
- ccl_global Ray *Ray_coop, /* Required for setting up ray for next iteration */
- ccl_global PathState *PathState_coop, /* Required for setting up ray for next iteration */
- ccl_global Ray *LightRay_dl_coop, /* Required for radiance update - direct lighting */
- ccl_global int *ISLamp_coop, /* Required for radiance update - direct lighting */
- ccl_global BsdfEval *BSDFEval_coop, /* Required for radiance update - direct lighting */
- ccl_global Ray *LightRay_ao_coop, /* Required for radiance update - AO */
- ccl_global float3 *AOBSDF_coop, /* Required for radiance update - AO */
- ccl_global float3 *AOAlpha_coop, /* Required for radiance update - AO */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- ccl_global char *use_queues_flag, /* flag to decide if scene_intersect kernel should
- * use queues to fetch ray index */
- int ray_index)
+ccl_device void kernel_next_iteration_setup(KernelGlobals *kg,
+ ccl_local_param unsigned int *local_queue_atomics)
{
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ if(ccl_global_id(0) == 0 && ccl_global_id(1) == 0) {
+ /* If we are here, then it means that scene-intersect kernel
+ * has already been executed atleast once. From the next time,
+ * scene-intersect kernel may operate on queues to fetch ray index
+ */
+ *kernel_split_params.use_queues_flag = 1;
+
+ /* Mark queue indices of QUEUE_SHADOW_RAY_CAST_AO_RAYS and
+ * QUEUE_SHADOW_RAY_CAST_DL_RAYS queues that were made empty during the
+ * previous kernel.
+ */
+ kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS] = 0;
+ kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS] = 0;
+ }
+
char enqueue_flag = 0;
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
/* Load ShaderData structure. */
PathRadiance *L = NULL;
ccl_global PathState *state = NULL;
+ ccl_global char *ray_state = kernel_split_state.ray_state;
/* Path radiance update for AO/Direct_lighting's shadow blocked. */
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) ||
IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO))
{
- state = &PathState_coop[ray_index];
- L = &PathRadiance_coop[ray_index];
- float3 _throughput = throughput_coop[ray_index];
+ state = &kernel_split_state.path_state[ray_index];
+ L = &kernel_split_state.path_radiance[ray_index];
+ float3 _throughput = kernel_split_state.throughput[ray_index];
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) {
- float3 shadow = LightRay_ao_coop[ray_index].P;
- char update_path_radiance = LightRay_ao_coop[ray_index].t;
+ float3 shadow = kernel_split_state.ao_light_ray[ray_index].P;
+ // TODO(mai): investigate correctness here
+ char update_path_radiance = (char)kernel_split_state.ao_light_ray[ray_index].t;
if(update_path_radiance) {
path_radiance_accum_ao(L,
_throughput,
- AOAlpha_coop[ray_index],
- AOBSDF_coop[ray_index],
+ kernel_split_state.ao_alpha[ray_index],
+ kernel_split_state.ao_bsdf[ray_index],
shadow,
state->bounce);
}
+ else {
+ path_radiance_accum_total_ao(L, _throughput, kernel_split_state.ao_bsdf[ray_index]);
+ }
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO);
}
if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) {
- float3 shadow = LightRay_dl_coop[ray_index].P;
- char update_path_radiance = LightRay_dl_coop[ray_index].t;
+ float3 shadow = kernel_split_state.light_ray[ray_index].P;
+ // TODO(mai): investigate correctness here
+ char update_path_radiance = (char)kernel_split_state.light_ray[ray_index].t;
+ BsdfEval L_light = kernel_split_state.bsdf_eval[ray_index];
if(update_path_radiance) {
- BsdfEval L_light = BSDFEval_coop[ray_index];
path_radiance_accum_light(L,
_throughput,
&L_light,
shadow,
1.0f,
state->bounce,
- ISLamp_coop[ray_index]);
+ kernel_split_state.is_lamp[ray_index]);
+ }
+ else {
+ path_radiance_accum_total_light(L, _throughput, &L_light);
}
REMOVE_RAY_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL);
}
}
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- ccl_global float3 *throughput = &throughput_coop[ray_index];
- ccl_global Ray *ray = &Ray_coop[ray_index];
- ccl_global RNG *rng = &rng_coop[ray_index];
- state = &PathState_coop[ray_index];
- L = &PathRadiance_coop[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
+ state = &kernel_split_state.path_state[ray_index];
+ L = &kernel_split_state.path_radiance[ray_index];
/* Compute direct lighting and next bounce. */
- if(!kernel_path_surface_bounce(kg, rng, sd, throughput, state, L, ray)) {
+ if(!kernel_path_surface_bounce(kg, &rng, &kernel_split_state.sd[ray_index], throughput, state, L, ray)) {
ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
enqueue_flag = 1;
}
+ kernel_split_state.rng[ray_index] = rng;
}
- return enqueue_flag;
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_UPDATE_BUFFER rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_path_init.h b/intern/cycles/kernel/split/kernel_path_init.h
new file mode 100644
index 00000000000..a7ecde7c80d
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_path_init.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* This kernel initializes structures needed in path-iteration kernels.
+ * This is the first kernel in ray-tracing logic.
+ *
+ * Ray state of rays outside the tile-boundary will be marked RAY_INACTIVE
+ */
+ccl_device void kernel_path_init(KernelGlobals *kg) {
+ int ray_index = ccl_global_id(0) + ccl_global_id(1) * ccl_global_size(0);
+
+ /* This is the first assignment to ray_state;
+ * So we dont use ASSIGN_RAY_STATE macro.
+ */
+ kernel_split_state.ray_state[ray_index] = RAY_ACTIVE;
+
+ unsigned int my_sample;
+ unsigned int pixel_x;
+ unsigned int pixel_y;
+ unsigned int tile_x;
+ unsigned int tile_y;
+
+ unsigned int work_index = 0;
+ /* Get work. */
+ if(!get_next_work(kg, &work_index, ray_index)) {
+ /* No more work, mark ray as inactive */
+ kernel_split_state.ray_state[ray_index] = RAY_INACTIVE;
+
+ return;
+ }
+
+ /* Get the sample associated with the work. */
+ my_sample = get_work_sample(kg, work_index, ray_index) + kernel_split_params.start_sample;
+
+ /* Get pixel and tile position associated with the work. */
+ get_work_pixel_tile_position(kg, &pixel_x, &pixel_y,
+ &tile_x, &tile_y,
+ work_index,
+ ray_index);
+ kernel_split_state.work_array[ray_index] = work_index;
+
+ ccl_global uint *rng_state = kernel_split_params.rng_state;
+ rng_state += kernel_split_params.offset + pixel_x + pixel_y*kernel_split_params.stride;
+
+ ccl_global float *buffer = kernel_split_params.buffer;
+ buffer += (kernel_split_params.offset + pixel_x + pixel_y * kernel_split_params.stride) * kernel_data.film.pass_stride;
+
+ RNG rng = kernel_split_state.rng[ray_index];
+
+ /* Initialize random numbers and ray. */
+ kernel_path_trace_setup(kg,
+ rng_state,
+ my_sample,
+ pixel_x, pixel_y,
+ &rng,
+ &kernel_split_state.ray[ray_index]);
+
+ if(kernel_split_state.ray[ray_index].t != 0.0f) {
+ /* Initialize throughput, L_transparent, Ray, PathState;
+ * These rays proceed with path-iteration.
+ */
+ kernel_split_state.throughput[ray_index] = make_float3(1.0f, 1.0f, 1.0f);
+ kernel_split_state.L_transparent[ray_index] = 0.0f;
+ path_radiance_init(&kernel_split_state.path_radiance[ray_index], kernel_data.film.use_light_pass);
+ path_state_init(kg,
+ &kernel_split_state.sd_DL_shadow[ray_index],
+ &kernel_split_state.path_state[ray_index],
+ &rng,
+ my_sample,
+ &kernel_split_state.ray[ray_index]);
+#ifdef __SUBSURFACE__
+ kernel_path_subsurface_init_indirect(&kernel_split_state.ss_rays[ray_index]);
+#endif
+
+#ifdef __KERNEL_DEBUG__
+ debug_data_init(&kernel_split_state.debug_data[ray_index]);
+#endif
+ }
+ else {
+ /* These rays do not participate in path-iteration. */
+ float4 L_rad = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+ /* Accumulate result in output buffer. */
+ kernel_write_pass_float4(buffer, my_sample, L_rad);
+ path_rng_end(kg, rng_state, kernel_split_state.rng[ray_index]);
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE);
+ }
+ kernel_split_state.rng[ray_index] = rng;
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_queue_enqueue.h b/intern/cycles/kernel/split/kernel_queue_enqueue.h
new file mode 100644
index 00000000000..e2e841f36d3
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_queue_enqueue.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* This kernel enqueues rays of different ray state into their
+ * appropriate queues:
+ *
+ * 1. Rays that have been determined to hit the background from the
+ * "kernel_scene_intersect" kernel are enqueued in
+ * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
+ * 2. Rays that have been determined to be actively participating in pat
+ * -iteration will be enqueued into QUEUE_ACTIVE_AND_REGENERATED_RAYS.
+ *
+ * State of queue during other times this kernel is called:
+ * At entry,
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be empty.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will contain RAY_TO_REGENERATE
+ * and RAY_UPDATE_BUFFER rays.
+ * At exit,
+ * - QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE rays.
+ * - QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with
+ * RAY_TO_REGENERATE, RAY_UPDATE_BUFFER, RAY_HIT_BACKGROUND rays.
+ */
+ccl_device void kernel_queue_enqueue(KernelGlobals *kg,
+ ccl_local_param QueueEnqueueLocals *locals)
+{
+ /* We have only 2 cases (Hit/Not-Hit) */
+ int lidx = ccl_local_id(1) * ccl_local_size(0) + ccl_local_id(0);
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+
+ if(lidx == 0) {
+ locals->queue_atomics[0] = 0;
+ locals->queue_atomics[1] = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int queue_number = -1;
+
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_UPDATE_BUFFER)) {
+ queue_number = QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS;
+ }
+ else if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE) ||
+ IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED)) {
+ queue_number = QUEUE_ACTIVE_AND_REGENERATED_RAYS;
+ }
+
+ unsigned int my_lqidx;
+ if(queue_number != -1) {
+ my_lqidx = get_local_queue_index(queue_number, locals->queue_atomics);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ if(lidx == 0) {
+ locals->queue_atomics[QUEUE_ACTIVE_AND_REGENERATED_RAYS] =
+ get_global_per_queue_offset(QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ locals->queue_atomics,
+ kernel_split_params.queue_index);
+ locals->queue_atomics[QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS] =
+ get_global_per_queue_offset(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ locals->queue_atomics,
+ kernel_split_params.queue_index);
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ unsigned int my_gqidx;
+ if(queue_number != -1) {
+ my_gqidx = get_global_queue_index(queue_number,
+ kernel_split_params.queue_size,
+ my_lqidx,
+ locals->queue_atomics);
+ kernel_split_state.queue_data[my_gqidx] = ray_index;
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_scene_intersect.h b/intern/cycles/kernel/split/kernel_scene_intersect.h
index 2388580051f..684760eedee 100644
--- a/intern/cycles/kernel/split/kernel_scene_intersect.h
+++ b/intern/cycles/kernel/split/kernel_scene_intersect.h
@@ -14,81 +14,47 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_scene_intersect kernel.
- * This is the second kernel in the ray tracing logic. This is the first
- * of the path iteration kernels. This kernel takes care of scene_intersect function.
+/* This kernel takes care of scene_intersect function.
*
* This kernel changes the ray_state of RAY_REGENERATED rays to RAY_ACTIVE.
* This kernel processes rays of ray state RAY_ACTIVE
- * This kernel determines the rays that have hit the background and changes their ray state to RAY_HIT_BACKGROUND.
- *
- * The input and output are as follows,
- *
- * Ray_coop ---------------------------------------|--------- kernel_scene_intersect----------|--- PathState
- * PathState_coop ---------------------------------| |--- Intersection
- * ray_state --------------------------------------| |--- ray_state
- * use_queues_flag --------------------------------| |
- * QueueData(QUEUE_ACTIVE_AND_REGENERATED_RAYS) ---| |
- * kg (globals) -----------------------------------| |
- * rng_coop ---------------------------------------| |
- * sw ---------------------------------------------| |
- * sh ---------------------------------------------| |
- * queuesize --------------------------------------| |
- *
- * Note on Queues :
- * Ideally we would want kernel_scene_intersect to work on queues.
- * But during the very first time, the queues will be empty and hence we perform a direct mapping
- * between ray-index and thread-index; From the next time onward, the queue will be filled and
- * we may start operating on queues.
- *
- * State of queue during the first time this kernel is called :
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.before and after this kernel
- *
- * State of queues during other times this kernel is called :
- * At entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will have a mix of RAY_ACTIVE, RAY_UPDATE_BUFFER and RAY_REGENERATED rays;
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE and RAY_UPDATE_BUFFER rays ;
- * (The rays that are in the state RAY_UPDATE_BUFFER in both the queues are actually the same rays; These
- * are the rays that were in RAY_ACTIVE state during the initial enqueue but on further processing
- * , by different kernels, have turned into RAY_UPDATE_BUFFER rays. Since all kernel, even after fetching from
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS, proceed further based on ray state information, RAY_UPDATE_BUFFER rays
- * being present in QUEUE_ACTIVE_AND_REGENERATED_RAYS does not cause any logical issues)
- * At exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS - All RAY_REGENERATED rays will have been converted to RAY_ACTIVE and
- * Some rays in QUEUE_ACTIVE_AND_REGENERATED_RAYS queue will move to state RAY_HIT_BACKGROUND
- * QUEUE_HITBF_BUFF_UPDATE_TOREGEN_RAYS - no change
+ * This kernel determines the rays that have hit the background and changes
+ * their ray state to RAY_HIT_BACKGROUND.
*/
-
-ccl_device void kernel_scene_intersect(
- KernelGlobals *kg,
- ccl_global uint *rng_coop,
- ccl_global Ray *Ray_coop, /* Required for scene_intersect */
- ccl_global PathState *PathState_coop, /* Required for scene_intersect */
- Intersection *Intersection_coop, /* Required for scene_intersect */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int sw, int sh,
- ccl_global char *use_queues_flag, /* used to decide if this kernel should use
- * queues to fetch ray index */
-#ifdef __KERNEL_DEBUG__
- DebugData *debugdata_coop,
-#endif
- int ray_index)
+ccl_device void kernel_scene_intersect(KernelGlobals *kg)
{
+ /* Fetch use_queues_flag */
+ char local_use_queues_flag = *kernel_split_params.use_queues_flag;
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(local_use_queues_flag) {
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+ }
+
/* All regenerated rays become active here */
- if(IS_STATE(ray_state, ray_index, RAY_REGENERATED))
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_ACTIVE);
+ if(IS_STATE(kernel_split_state.ray_state, ray_index, RAY_REGENERATED))
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE);
- if(!IS_STATE(ray_state, ray_index, RAY_ACTIVE))
+ if(!IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE))
return;
#ifdef __KERNEL_DEBUG__
- DebugData *debug_data = &debugdata_coop[ray_index];
+ DebugData *debug_data = &kernel_split_state.debug_data[ray_index];
#endif
- Intersection *isect = &Intersection_coop[ray_index];
- PathState state = PathState_coop[ray_index];
- Ray ray = Ray_coop[ray_index];
+ Intersection isect;
+ PathState state = kernel_split_state.path_state[ray_index];
+ Ray ray = kernel_split_state.ray[ray_index];
/* intersect scene */
uint visibility = path_state_ray_visibility(kg, &state);
@@ -96,7 +62,7 @@ ccl_device void kernel_scene_intersect(
#ifdef __HAIR__
float difl = 0.0f, extmax = 0.0f;
uint lcg_state = 0;
- RNG rng = rng_coop[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
if(kernel_data.bvh.have_curves) {
if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
@@ -106,19 +72,25 @@ ccl_device void kernel_scene_intersect(
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_state_init(&rng, &state, 0x51633e2d);
+ lcg_state = lcg_state_init(&rng, state.rng_offset, state.sample, 0x51633e2d);
+ }
+
+ if(state.bounce > kernel_data.integrator.ao_bounces) {
+ visibility = PATH_RAY_SHADOW;
+ ray.t = kernel_data.background.ao_distance;
}
- bool hit = scene_intersect(kg, ray, visibility, isect, &lcg_state, difl, extmax);
+ bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
#else
- bool hit = scene_intersect(kg, ray, visibility, isect, NULL, 0.0f, 0.0f);
+ bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
#endif
+ kernel_split_state.isect[ray_index] = isect;
#ifdef __KERNEL_DEBUG__
if(state.flag & PATH_RAY_CAMERA) {
- debug_data->num_bvh_traversed_nodes += isect->num_traversed_nodes;
- debug_data->num_bvh_traversed_instances += isect->num_traversed_instances;
- debug_data->num_bvh_intersections += isect->num_intersections;
+ debug_data->num_bvh_traversed_nodes += isect.num_traversed_nodes;
+ debug_data->num_bvh_traversed_instances += isect.num_traversed_instances;
+ debug_data->num_bvh_intersections += isect.num_intersections;
}
debug_data->num_ray_bounces++;
#endif
@@ -128,6 +100,8 @@ ccl_device void kernel_scene_intersect(
* These rays undergo special processing in the
* background_bufferUpdate kernel.
*/
- ASSIGN_RAY_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND);
+ ASSIGN_RAY_STATE(kernel_split_state.ray_state, ray_index, RAY_HIT_BACKGROUND);
}
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shader_eval.h b/intern/cycles/kernel/split/kernel_shader_eval.h
index cef64bf5f36..0f1696e34a0 100644
--- a/intern/cycles/kernel/split/kernel_shader_eval.h
+++ b/intern/cycles/kernel/split/kernel_shader_eval.h
@@ -14,57 +14,58 @@
* limitations under the License.
*/
-#include "kernel_split_common.h"
+CCL_NAMESPACE_BEGIN
-/* Note on kernel_shader_eval kernel
- * This kernel is the 5th kernel in the ray tracing logic. This is
- * the 4rd kernel in path iteration. This kernel sets up the ShaderData
- * structure from the values computed by the previous kernels. It also identifies
- * the rays of state RAY_TO_REGENERATE and enqueues them in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
+/* This kernel sets up the ShaderData structure from the values computed
+ * by the previous kernels.
*
- * The input and output of the kernel is as follows,
- * rng_coop -------------------------------------------|--- kernel_shader_eval --|--- sd
- * Ray_coop -------------------------------------------| |--- Queue_data (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * PathState_coop -------------------------------------| |--- Queue_index (QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)
- * Intersection_coop ----------------------------------| |
- * Queue_data (QUEUE_ACTIVE_AND_REGENERATD_RAYS)-------| |
- * Queue_index(QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS)---| |
- * ray_state ------------------------------------------| |
- * kg (globals) ---------------------------------------| |
- * queuesize ------------------------------------------| |
- *
- * Note on Queues :
- * This kernel reads from the QUEUE_ACTIVE_AND_REGENERATED_RAYS queue and processes
- * only the rays of state RAY_ACTIVE;
- * State of queues when this kernel is called,
- * at entry,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be empty.
- * at exit,
- * QUEUE_ACTIVE_AND_REGENERATED_RAYS will be filled with RAY_ACTIVE and RAY_REGENERATED rays
- * QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be filled with RAY_TO_REGENERATE rays
+ * It also identifies the rays of state RAY_TO_REGENERATE and enqueues them
+ * in QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue.
*/
-ccl_device void kernel_shader_eval(
- KernelGlobals *kg,
- ShaderData *sd, /* Output ShaderData structure to be filled */
- ccl_global uint *rng_coop, /* Required for rbsdf calculation */
- ccl_global Ray *Ray_coop, /* Required for setting up shader from ray */
- ccl_global PathState *PathState_coop, /* Required for all functions in this kernel */
- Intersection *Intersection_coop, /* Required for setting up shader from ray */
- ccl_global char *ray_state, /* Denotes the state of each ray */
- int ray_index)
+ccl_device void kernel_shader_eval(KernelGlobals *kg,
+ ccl_local_param unsigned int *local_queue_atomics)
{
- if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
- Intersection *isect = &Intersection_coop[ray_index];
- ccl_global uint *rng = &rng_coop[ray_index];
- ccl_global PathState *state = &PathState_coop[ray_index];
- Ray ray = Ray_coop[ray_index];
+ /* Enqeueue RAY_TO_REGENERATE rays into QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS queue. */
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+ char enqueue_flag = 0;
+ if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_TO_REGENERATE)) {
+ enqueue_flag = 1;
+ }
+
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+
+ /* Continue on with shader evaluation. */
+ if((ray_index != QUEUE_EMPTY_SLOT) && IS_STATE(kernel_split_state.ray_state, ray_index, RAY_ACTIVE)) {
+ Intersection isect = kernel_split_state.isect[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ Ray ray = kernel_split_state.ray[ray_index];
shader_setup_from_ray(kg,
- sd,
- isect,
+ &kernel_split_state.sd[ray_index],
+ &isect,
&ray);
- float rbsdf = path_state_rng_1D_for_decision(kg, rng, state, PRNG_BSDF);
- shader_eval_surface(kg, sd, rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ float rbsdf = path_state_rng_1D_for_decision(kg, &rng, state, PRNG_BSDF);
+ shader_eval_surface(kg, &kernel_split_state.sd[ray_index], &rng, state, rbsdf, state->flag, SHADER_CONTEXT_MAIN);
+ kernel_split_state.rng[ray_index] = rng;
}
}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked.h b/intern/cycles/kernel/split/kernel_shadow_blocked.h
deleted file mode 100644
index 6153af47f96..00000000000
--- a/intern/cycles/kernel/split/kernel_shadow_blocked.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2011-2015 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 "kernel_split_common.h"
-
-/* Note on kernel_shadow_blocked kernel.
- * This is the ninth kernel in the ray tracing logic. This is the eighth
- * of the path iteration kernels. This kernel takes care of "shadow ray cast"
- * logic of the direct lighting and AO part of ray tracing.
- *
- * The input and output are as follows,
- *
- * PathState_coop ----------------------------------|--- kernel_shadow_blocked --|
- * LightRay_dl_coop --------------------------------| |--- LightRay_dl_coop
- * LightRay_ao_coop --------------------------------| |--- LightRay_ao_coop
- * ray_state ---------------------------------------| |--- ray_state
- * Queue_data(QUEUE_SHADOW_RAY_CAST_AO_RAYS & | |--- Queue_data (QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_AO_RAYS)
- QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| |
- * Queue_index(QUEUE_SHADOW_RAY_CAST_AO_RAYS&
- QUEUE_SHADOW_RAY_CAST_DL_RAYS) -------| |
- * kg (globals) ------------------------------------| |
- * queuesize ---------------------------------------| |
- *
- * Note on sd_shadow : sd_shadow is neither input nor output to this kernel. sd_shadow is filled and consumed in this kernel itself.
- * Note on queues :
- * The kernel fetches from QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS queues. We will empty
- * these queues this kernel.
- * State of queues when this kernel is called :
- * state of queues QUEUE_ACTIVE_AND_REGENERATED_RAYS and QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS will be same
- * before and after this kernel call.
- * QUEUE_SHADOW_RAY_CAST_AO_RAYS & QUEUE_SHADOW_RAY_CAST_DL_RAYS will be filled with rays marked with flags RAY_SHADOW_RAY_CAST_AO
- * and RAY_SHADOW_RAY_CAST_DL respectively, during kernel entry.
- * QUEUE_SHADOW_RAY_CAST_AO_RAYS and QUEUE_SHADOW_RAY_CAST_DL_RAYS will be empty at kernel exit.
- */
-ccl_device void kernel_shadow_blocked(
- KernelGlobals *kg,
- ccl_global PathState *PathState_coop, /* Required for shadow blocked */
- ccl_global Ray *LightRay_dl_coop, /* Required for direct lighting's shadow blocked */
- ccl_global Ray *LightRay_ao_coop, /* Required for AO's shadow blocked */
- ccl_global char *ray_state,
- char shadow_blocked_type,
- int ray_index)
-{
- /* Flag determining if we need to update L. */
- char update_path_radiance = 0;
-
- if(IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL) ||
- IS_FLAG(ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO))
- {
- ccl_global PathState *state = &PathState_coop[ray_index];
- ccl_global Ray *light_ray_dl_global = &LightRay_dl_coop[ray_index];
- ccl_global Ray *light_ray_ao_global = &LightRay_ao_coop[ray_index];
-
- ccl_global Ray *light_ray_global =
- shadow_blocked_type == RAY_SHADOW_RAY_CAST_AO
- ? light_ray_ao_global
- : light_ray_dl_global;
-
- float3 shadow;
- update_path_radiance = !(shadow_blocked(kg,
- kg->sd_input,
- state,
- light_ray_global,
- &shadow));
-
- /* We use light_ray_global's P and t to store shadow and
- * update_path_radiance.
- */
- light_ray_global->P = shadow;
- light_ray_global->t = update_path_radiance;
- }
-}
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
new file mode 100644
index 00000000000..4243e18de72
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_ao.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011-2015 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Shadow ray cast for AO. */
+ccl_device void kernel_shadow_blocked_ao(KernelGlobals *kg)
+{
+ unsigned int ao_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_AO_RAYS];
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = QUEUE_EMPTY_SLOT;
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(thread_index < ao_queue_length) {
+ ray_index = get_ray_index(kg, thread_index, QUEUE_SHADOW_RAY_CAST_AO_RAYS,
+ kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
+ }
+
+ if(ray_index == QUEUE_EMPTY_SLOT)
+ return;
+
+ /* Flag determining if we need to update L. */
+ char update_path_radiance = 0;
+
+ if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_AO)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ ccl_global Ray *light_ray_global = &kernel_split_state.ao_light_ray[ray_index];
+
+ float3 shadow;
+ Ray ray = *light_ray_global;
+ update_path_radiance = !(shadow_blocked(kg,
+ &kernel_split_state.sd_DL_shadow[ray_index],
+ state,
+ &ray,
+ &shadow));
+
+ *light_ray_global = ray;
+ /* We use light_ray_global's P and t to store shadow and
+ * update_path_radiance.
+ */
+ light_ray_global->P = shadow;
+ light_ray_global->t = update_path_radiance;
+ }
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
new file mode 100644
index 00000000000..bb8f0157965
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_shadow_blocked_dl.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011-2015 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+/* Shadow ray cast for direct visible light. */
+ccl_device void kernel_shadow_blocked_dl(KernelGlobals *kg)
+{
+ unsigned int dl_queue_length = kernel_split_params.queue_index[QUEUE_SHADOW_RAY_CAST_DL_RAYS];
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = QUEUE_EMPTY_SLOT;
+ int thread_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ if(thread_index < dl_queue_length) {
+ ray_index = get_ray_index(kg, thread_index, QUEUE_SHADOW_RAY_CAST_DL_RAYS,
+ kernel_split_state.queue_data, kernel_split_params.queue_size, 1);
+ }
+
+ if(ray_index == QUEUE_EMPTY_SLOT)
+ return;
+
+ /* Flag determining if we need to update L. */
+ char update_path_radiance = 0;
+
+ if(IS_FLAG(kernel_split_state.ray_state, ray_index, RAY_SHADOW_RAY_CAST_DL)) {
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ ccl_global Ray *light_ray_global = &kernel_split_state.light_ray[ray_index];
+
+ float3 shadow;
+ Ray ray = *light_ray_global;
+ update_path_radiance = !(shadow_blocked(kg,
+ &kernel_split_state.sd_DL_shadow[ray_index],
+ state,
+ &ray,
+ &shadow));
+
+ *light_ray_global = ray;
+ /* We use light_ray_global's P and t to store shadow and
+ * update_path_radiance.
+ */
+ light_ray_global->P = shadow;
+ light_ray_global->t = update_path_radiance;
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_split_common.h b/intern/cycles/kernel/split/kernel_split_common.h
index 2135ee22b2e..4303ba0a905 100644
--- a/intern/cycles/kernel/split/kernel_split_common.h
+++ b/intern/cycles/kernel/split/kernel_split_common.h
@@ -17,48 +17,61 @@
#ifndef __KERNEL_SPLIT_H__
#define __KERNEL_SPLIT_H__
-#include "kernel_compat_opencl.h"
-#include "kernel_math.h"
-#include "kernel_types.h"
-#include "kernel_globals.h"
-#include "kernel_image_opencl.h"
+#include "kernel/kernel_math.h"
+#include "kernel/kernel_types.h"
-#include "util_atomic.h"
+#include "kernel/split/kernel_split_data.h"
-#include "kernel_random.h"
-#include "kernel_projection.h"
-#include "kernel_montecarlo.h"
-#include "kernel_differential.h"
-#include "kernel_camera.h"
+#include "kernel/kernel_globals.h"
-#include "geom/geom.h"
-#include "bvh/bvh.h"
+#ifdef __OSL__
+# include "kernel/osl/osl_shader.h"
+#endif
+
+#ifdef __KERNEL_OPENCL__
+# include "kernel/kernel_image_opencl.h"
+#endif
+#ifdef __KERNEL_CPU__
+# include "kernel/kernels/cpu/kernel_cpu_image.h"
+#endif
+
+#include "util/util_atomic.h"
+
+#include "kernel/kernel_random.h"
+#include "kernel/kernel_projection.h"
+#include "kernel/kernel_montecarlo.h"
+#include "kernel/kernel_differential.h"
+#include "kernel/kernel_camera.h"
+
+#include "kernel/geom/geom.h"
+#include "kernel/bvh/bvh.h"
-#include "kernel_accumulate.h"
-#include "kernel_shader.h"
-#include "kernel_light.h"
-#include "kernel_passes.h"
+#include "kernel/kernel_accumulate.h"
+#include "kernel/kernel_shader.h"
+#include "kernel/kernel_light.h"
+#include "kernel/kernel_passes.h"
#ifdef __SUBSURFACE__
-#include "kernel_subsurface.h"
+# include "kernel/kernel_subsurface.h"
#endif
#ifdef __VOLUME__
-#include "kernel_volume.h"
+# include "kernel/kernel_volume.h"
#endif
-#include "kernel_path_state.h"
-#include "kernel_shadow.h"
-#include "kernel_emission.h"
-#include "kernel_path_common.h"
-#include "kernel_path_surface.h"
-#include "kernel_path_volume.h"
+#include "kernel/kernel_path_state.h"
+#include "kernel/kernel_shadow.h"
+#include "kernel/kernel_emission.h"
+#include "kernel/kernel_path_common.h"
+#include "kernel/kernel_path_surface.h"
+#include "kernel/kernel_path_volume.h"
+#include "kernel/kernel_path_subsurface.h"
#ifdef __KERNEL_DEBUG__
-#include "kernel_debug.h"
+# include "kernel/kernel_debug.h"
#endif
-#include "kernel_queues.h"
-#include "kernel_work_stealing.h"
+#include "kernel/kernel_queues.h"
+#include "kernel/kernel_work_stealing.h"
#endif /* __KERNEL_SPLIT_H__ */
diff --git a/intern/cycles/kernel/split/kernel_split_data.h b/intern/cycles/kernel/split/kernel_split_data.h
new file mode 100644
index 00000000000..17e6587883a
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_split_data.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KERNEL_SPLIT_DATA_H__
+#define __KERNEL_SPLIT_DATA_H__
+
+#include "kernel/split/kernel_split_data_types.h"
+#include "kernel/kernel_globals.h"
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_inline uint64_t split_data_buffer_size(KernelGlobals *kg, size_t num_elements)
+{
+ (void)kg; /* Unused on CPU. */
+
+ uint64_t size = 0;
+#define SPLIT_DATA_ENTRY(type, name, num) + align_up(num_elements * num * sizeof(type), 16)
+ size = size SPLIT_DATA_ENTRIES;
+#undef SPLIT_DATA_ENTRY
+
+#ifdef __SUBSURFACE__
+ size += align_up(num_elements * sizeof(SubsurfaceIndirectRays), 16); /* ss_rays */
+#endif
+
+#ifdef __VOLUME__
+ size += align_up(2 * num_elements * sizeof(PathState), 16); /* state_shadow */
+#endif
+
+ return size;
+}
+
+ccl_device_inline void split_data_init(KernelGlobals *kg,
+ ccl_global SplitData *split_data,
+ size_t num_elements,
+ ccl_global void *data,
+ ccl_global char *ray_state)
+{
+ (void)kg; /* Unused on CPU. */
+
+ ccl_global char *p = (ccl_global char*)data;
+
+#define SPLIT_DATA_ENTRY(type, name, num) \
+ split_data->name = (type*)p; p += align_up(num_elements * num * sizeof(type), 16);
+ SPLIT_DATA_ENTRIES;
+#undef SPLIT_DATA_ENTRY
+
+#ifdef __SUBSURFACE__
+ split_data->ss_rays = (ccl_global SubsurfaceIndirectRays*)p;
+ p += align_up(num_elements * sizeof(SubsurfaceIndirectRays), 16);
+#endif
+
+#ifdef __VOLUME__
+ split_data->state_shadow = (ccl_global PathState*)p;
+ p += align_up(2 * num_elements * sizeof(PathState), 16);
+#endif
+
+ split_data->ray_state = ray_state;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_SPLIT_DATA_H__ */
diff --git a/intern/cycles/kernel/split/kernel_split_data_types.h b/intern/cycles/kernel/split/kernel_split_data_types.h
new file mode 100644
index 00000000000..748197b7183
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_split_data_types.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2011-2016 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KERNEL_SPLIT_DATA_TYPES_H__
+#define __KERNEL_SPLIT_DATA_TYPES_H__
+
+CCL_NAMESPACE_BEGIN
+
+/* parameters used by the split kernels, we use a single struct to avoid passing these to each kernel */
+
+typedef struct SplitParams {
+ int x;
+ int y;
+ int w;
+ int h;
+
+ int offset;
+ int stride;
+
+ ccl_global uint *rng_state;
+
+ int start_sample;
+ int end_sample;
+
+ ccl_global unsigned int *work_pools;
+ unsigned int num_samples;
+
+ ccl_global int *queue_index;
+ int queue_size;
+ ccl_global char *use_queues_flag;
+
+ ccl_global float *buffer;
+} SplitParams;
+
+/* Global memory variables [porting]; These memory is used for
+ * co-operation between different kernels; Data written by one
+ * kernel will be available to another kernel via this global
+ * memory.
+ */
+
+/* SPLIT_DATA_ENTRY(type, name, num) */
+
+#if defined(WITH_CYCLES_DEBUG) || defined(__KERNEL_DEBUG__)
+/* DebugData memory */
+# define SPLIT_DATA_DEBUG_ENTRIES \
+ SPLIT_DATA_ENTRY(DebugData, debug_data, 1)
+#else
+# define SPLIT_DATA_DEBUG_ENTRIES
+#endif
+
+#define SPLIT_DATA_ENTRIES \
+ SPLIT_DATA_ENTRY(ccl_global RNG, rng, 1) \
+ SPLIT_DATA_ENTRY(ccl_global float3, throughput, 1) \
+ SPLIT_DATA_ENTRY(ccl_global float, L_transparent, 1) \
+ SPLIT_DATA_ENTRY(PathRadiance, path_radiance, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, ray, 1) \
+ SPLIT_DATA_ENTRY(ccl_global PathState, path_state, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Intersection, isect, 1) \
+ SPLIT_DATA_ENTRY(ccl_global float3, ao_alpha, 1) \
+ SPLIT_DATA_ENTRY(ccl_global float3, ao_bsdf, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, ao_light_ray, 1) \
+ SPLIT_DATA_ENTRY(ccl_global BsdfEval, bsdf_eval, 1) \
+ SPLIT_DATA_ENTRY(ccl_global int, is_lamp, 1) \
+ SPLIT_DATA_ENTRY(ccl_global Ray, light_ray, 1) \
+ SPLIT_DATA_ENTRY(ccl_global int, queue_data, (NUM_QUEUES*2)) /* TODO(mai): this is too large? */ \
+ SPLIT_DATA_ENTRY(ccl_global uint, work_array, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, sd, 1) \
+ SPLIT_DATA_ENTRY(ShaderData, sd_DL_shadow, 1) \
+ SPLIT_DATA_DEBUG_ENTRIES \
+
+/* struct that holds pointers to data in the shared state buffer */
+typedef struct SplitData {
+#define SPLIT_DATA_ENTRY(type, name, num) type *name;
+ SPLIT_DATA_ENTRIES
+#undef SPLIT_DATA_ENTRY
+
+#ifdef __SUBSURFACE__
+ ccl_global SubsurfaceIndirectRays *ss_rays;
+#endif
+
+#ifdef __VOLUME__
+ ccl_global PathState *state_shadow;
+#endif
+
+ /* this is actually in a separate buffer from the rest of the split state data (so it can be read back from
+ * the host easily) but is still used the same as the other data so we have it here in this struct as well
+ */
+ ccl_global char *ray_state;
+} SplitData;
+
+#ifndef __KERNEL_CUDA__
+# define kernel_split_state (kg->split_data)
+# define kernel_split_params (kg->split_param_data)
+#else
+__device__ SplitData __split_data;
+# define kernel_split_state (__split_data)
+__device__ SplitParams __split_param_data;
+# define kernel_split_params (__split_param_data)
+#endif /* __KERNEL_CUDA__ */
+
+/* Local storage for queue_enqueue kernel. */
+typedef struct QueueEnqueueLocals {
+ uint queue_atomics[2];
+} QueueEnqueueLocals;
+
+/* Local storage for holdout_emission_blurring_pathtermination_ao kernel. */
+typedef struct BackgroundAOLocals {
+ uint queue_atomics_bg;
+ uint queue_atomics_ao;
+} BackgroundAOLocals;
+
+CCL_NAMESPACE_END
+
+#endif /* __KERNEL_SPLIT_DATA_TYPES_H__ */
diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
new file mode 100644
index 00000000000..0b4d50c70ee
--- /dev/null
+++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2011-2017 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+
+ccl_device void kernel_subsurface_scatter(KernelGlobals *kg,
+ ccl_local_param unsigned int* local_queue_atomics)
+{
+#ifdef __SUBSURFACE__
+ if(ccl_local_id(0) == 0 && ccl_local_id(1) == 0) {
+ *local_queue_atomics = 0;
+ }
+ ccl_barrier(CCL_LOCAL_MEM_FENCE);
+
+ int ray_index = ccl_global_id(1) * ccl_global_size(0) + ccl_global_id(0);
+ ray_index = get_ray_index(kg, ray_index,
+ QUEUE_ACTIVE_AND_REGENERATED_RAYS,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_size,
+ 0);
+
+#ifdef __COMPUTE_DEVICE_GPU__
+ /* If we are executing on a GPU device, we exit all threads that are not
+ * required.
+ *
+ * If we are executing on a CPU device, then we need to keep all threads
+ * active since we have barrier() calls later in the kernel. CPU devices,
+ * expect all threads to execute barrier statement.
+ */
+ if(ray_index == QUEUE_EMPTY_SLOT) {
+ return;
+ }
+#endif
+
+ char enqueue_flag = 0;
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ if(ray_index != QUEUE_EMPTY_SLOT) {
+#endif
+
+ ccl_global char *ray_state = kernel_split_state.ray_state;
+ ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
+ PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
+ RNG rng = kernel_split_state.rng[ray_index];
+ ccl_global Ray *ray = &kernel_split_state.ray[ray_index];
+ ccl_global float3 *throughput = &kernel_split_state.throughput[ray_index];
+ ccl_global SubsurfaceIndirectRays *ss_indirect = &kernel_split_state.ss_rays[ray_index];
+ ShaderData *sd = &kernel_split_state.sd[ray_index];
+ ShaderData *emission_sd = &kernel_split_state.sd_DL_shadow[ray_index];
+
+ if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
+ if(sd->flag & SD_BSSRDF) {
+ if(kernel_path_subsurface_scatter(kg,
+ sd,
+ emission_sd,
+ L,
+ state,
+ &rng,
+ ray,
+ throughput,
+ ss_indirect)) {
+ ASSIGN_RAY_STATE(ray_state, ray_index, RAY_UPDATE_BUFFER);
+ enqueue_flag = 1;
+ }
+ }
+ kernel_split_state.rng[ray_index] = rng;
+ }
+
+#ifndef __COMPUTE_DEVICE_GPU__
+ }
+#endif
+
+ /* Enqueue RAY_UPDATE_BUFFER rays. */
+ enqueue_ray_index_local(ray_index,
+ QUEUE_HITBG_BUFF_UPDATE_TOREGEN_RAYS,
+ enqueue_flag,
+ kernel_split_params.queue_size,
+ local_queue_atomics,
+ kernel_split_state.queue_data,
+ kernel_split_params.queue_index);
+
+#endif /* __SUBSURFACE__ */
+
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/split/kernel_sum_all_radiance.h b/intern/cycles/kernel/split/kernel_sum_all_radiance.h
deleted file mode 100644
index a21e9b6a0b1..00000000000
--- a/intern/cycles/kernel/split/kernel_sum_all_radiance.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2011-2015 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 "../kernel_compat_opencl.h"
-#include "../kernel_math.h"
-#include "../kernel_types.h"
-#include "../kernel_globals.h"
-
-/* Since we process various samples in parallel; The output radiance of different samples
- * are stored in different locations; This kernel combines the output radiance contributed
- * by all different samples and stores them in the RenderTile's output buffer.
- */
-ccl_device void kernel_sum_all_radiance(
- ccl_constant KernelData *data, /* To get pass_stride to offet into buffer */
- ccl_global float *buffer, /* Output buffer of RenderTile */
- ccl_global float *per_sample_output_buffer, /* Radiance contributed by all samples */
- int parallel_samples, int sw, int sh, int stride,
- int buffer_offset_x,
- int buffer_offset_y,
- int buffer_stride,
- int start_sample)
-{
- int x = get_global_id(0);
- int y = get_global_id(1);
-
- if(x < sw && y < sh) {
- buffer += ((buffer_offset_x + x) + (buffer_offset_y + y) * buffer_stride) * (data->film.pass_stride);
- per_sample_output_buffer += ((x + y * stride) * parallel_samples) * (data->film.pass_stride);
-
- int sample_stride = (data->film.pass_stride);
-
- int sample_iterator = 0;
- int pass_stride_iterator = 0;
- int num_floats = data->film.pass_stride;
-
- for(sample_iterator = 0; sample_iterator < parallel_samples; sample_iterator++) {
- for(pass_stride_iterator = 0; pass_stride_iterator < num_floats; pass_stride_iterator++) {
- *(buffer + pass_stride_iterator) =
- (start_sample == 0 && sample_iterator == 0)
- ? *(per_sample_output_buffer + pass_stride_iterator)
- : *(buffer + pass_stride_iterator) + *(per_sample_output_buffer + pass_stride_iterator);
- }
- per_sample_output_buffer += sample_stride;
- }
- }
-}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index 88ec7fe6fcc..d748e76fa80 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -39,7 +39,7 @@
* mostly taken care of in the SVM compiler.
*/
-#include "svm_types.h"
+#include "kernel/svm/svm_types.h"
CCL_NAMESPACE_BEGIN
@@ -139,49 +139,49 @@ CCL_NAMESPACE_END
/* Nodes */
-#include "svm_noise.h"
+#include "kernel/svm/svm_noise.h"
#include "svm_texture.h"
-#include "svm_color_util.h"
-#include "svm_math_util.h"
-
-#include "svm_attribute.h"
-#include "svm_gradient.h"
-#include "svm_blackbody.h"
-#include "svm_closure.h"
-#include "svm_noisetex.h"
-#include "svm_convert.h"
-#include "svm_displace.h"
-#include "svm_fresnel.h"
-#include "svm_wireframe.h"
-#include "svm_wavelength.h"
-#include "svm_camera.h"
-#include "svm_geometry.h"
-#include "svm_hsv.h"
-#include "svm_image.h"
-#include "svm_gamma.h"
-#include "svm_brightness.h"
-#include "svm_invert.h"
-#include "svm_light_path.h"
-#include "svm_magic.h"
-#include "svm_mapping.h"
-#include "svm_normal.h"
-#include "svm_wave.h"
-#include "svm_math.h"
-#include "svm_mix.h"
-#include "svm_ramp.h"
-#include "svm_sepcomb_hsv.h"
-#include "svm_sepcomb_vector.h"
-#include "svm_musgrave.h"
-#include "svm_sky.h"
-#include "svm_tex_coord.h"
-#include "svm_value.h"
-#include "svm_voronoi.h"
-#include "svm_checker.h"
-#include "svm_brick.h"
-#include "svm_vector_transform.h"
-#include "svm_voxel.h"
-#include "svm_bump.h"
+#include "kernel/svm/svm_color_util.h"
+#include "kernel/svm/svm_math_util.h"
+
+#include "kernel/svm/svm_attribute.h"
+#include "kernel/svm/svm_gradient.h"
+#include "kernel/svm/svm_blackbody.h"
+#include "kernel/svm/svm_closure.h"
+#include "kernel/svm/svm_noisetex.h"
+#include "kernel/svm/svm_convert.h"
+#include "kernel/svm/svm_displace.h"
+#include "kernel/svm/svm_fresnel.h"
+#include "kernel/svm/svm_wireframe.h"
+#include "kernel/svm/svm_wavelength.h"
+#include "kernel/svm/svm_camera.h"
+#include "kernel/svm/svm_geometry.h"
+#include "kernel/svm/svm_hsv.h"
+#include "kernel/svm/svm_image.h"
+#include "kernel/svm/svm_gamma.h"
+#include "kernel/svm/svm_brightness.h"
+#include "kernel/svm/svm_invert.h"
+#include "kernel/svm/svm_light_path.h"
+#include "kernel/svm/svm_magic.h"
+#include "kernel/svm/svm_mapping.h"
+#include "kernel/svm/svm_normal.h"
+#include "kernel/svm/svm_wave.h"
+#include "kernel/svm/svm_math.h"
+#include "kernel/svm/svm_mix.h"
+#include "kernel/svm/svm_ramp.h"
+#include "kernel/svm/svm_sepcomb_hsv.h"
+#include "kernel/svm/svm_sepcomb_vector.h"
+#include "kernel/svm/svm_musgrave.h"
+#include "kernel/svm/svm_sky.h"
+#include "kernel/svm/svm_tex_coord.h"
+#include "kernel/svm/svm_value.h"
+#include "kernel/svm/svm_voronoi.h"
+#include "kernel/svm/svm_checker.h"
+#include "kernel/svm/svm_brick.h"
+#include "kernel/svm/svm_vector_transform.h"
+#include "kernel/svm/svm_voxel.h"
+#include "kernel/svm/svm_bump.h"
CCL_NAMESPACE_BEGIN
@@ -192,7 +192,7 @@ CCL_NAMESPACE_BEGIN
ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_addr_space PathState *state, ShaderType type, int path_flag)
{
float stack[SVM_STACK_SIZE];
- int offset = ccl_fetch(sd, shader) & SHADER_MASK;
+ int offset = sd->shader & SHADER_MASK;
while(1) {
uint4 node = read_node(kg, &offset);
diff --git a/intern/cycles/kernel/svm/svm_attribute.h b/intern/cycles/kernel/svm/svm_attribute.h
index 0e55c99ae97..229a3f20421 100644
--- a/intern/cycles/kernel/svm/svm_attribute.h
+++ b/intern/cycles/kernel/svm/svm_attribute.h
@@ -27,7 +27,7 @@ ccl_device AttributeDescriptor svm_node_attr_init(KernelGlobals *kg, ShaderData
AttributeDescriptor desc;
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ if(sd->object != OBJECT_NONE) {
desc = find_attribute(kg, sd, node.y);
if(desc.offset == ATTR_STD_NOT_FOUND) {
desc = attribute_not_found();
diff --git a/intern/cycles/kernel/svm/svm_bump.h b/intern/cycles/kernel/svm/svm_bump.h
index 04a8c7b64e5..610d9af9e1f 100644
--- a/intern/cycles/kernel/svm/svm_bump.h
+++ b/intern/cycles/kernel/svm/svm_bump.h
@@ -21,9 +21,9 @@ CCL_NAMESPACE_BEGIN
ccl_device void svm_node_enter_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset)
{
/* save state */
- stack_store_float3(stack, offset+0, ccl_fetch(sd, P));
- stack_store_float3(stack, offset+3, ccl_fetch(sd, dP).dx);
- stack_store_float3(stack, offset+6, ccl_fetch(sd, dP).dy);
+ stack_store_float3(stack, offset+0, sd->P);
+ stack_store_float3(stack, offset+3, sd->dP.dx);
+ stack_store_float3(stack, offset+6, sd->dP.dy);
/* set state as if undisplaced */
const AttributeDescriptor desc = find_attribute(kg, sd, ATTR_STD_POSITION_UNDISPLACED);
@@ -36,18 +36,18 @@ ccl_device void svm_node_enter_bump_eval(KernelGlobals *kg, ShaderData *sd, floa
object_dir_transform(kg, sd, &dPdx);
object_dir_transform(kg, sd, &dPdy);
- ccl_fetch(sd, P) = P;
- ccl_fetch(sd, dP).dx = dPdx;
- ccl_fetch(sd, dP).dy = dPdy;
+ sd->P = P;
+ sd->dP.dx = dPdx;
+ sd->dP.dy = dPdy;
}
}
ccl_device void svm_node_leave_bump_eval(KernelGlobals *kg, ShaderData *sd, float *stack, uint offset)
{
/* restore state */
- ccl_fetch(sd, P) = stack_load_float3(stack, offset+0);
- ccl_fetch(sd, dP).dx = stack_load_float3(stack, offset+3);
- ccl_fetch(sd, dP).dy = stack_load_float3(stack, offset+6);
+ sd->P = stack_load_float3(stack, offset+0);
+ sd->dP.dx = stack_load_float3(stack, offset+3);
+ sd->dP.dy = stack_load_float3(stack, offset+6);
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_camera.h b/intern/cycles/kernel/svm/svm_camera.h
index 00678a49d70..90249dfd978 100644
--- a/intern/cycles/kernel/svm/svm_camera.h
+++ b/intern/cycles/kernel/svm/svm_camera.h
@@ -23,7 +23,7 @@ ccl_device void svm_node_camera(KernelGlobals *kg, ShaderData *sd, float *stack,
float3 vector;
Transform tfm = kernel_data.cam.worldtocamera;
- vector = transform_point(&tfm, ccl_fetch(sd, P));
+ vector = transform_point(&tfm, sd->P);
zdepth = vector.z;
distance = len(vector);
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 017d697f9f8..1885e1af851 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -25,13 +25,13 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int t
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = eta;
- ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
+ sd->flag |= bsdf_refraction_setup(bsdf);
}
else {
bsdf->alpha_y = 0.0f;
bsdf->alpha_x = 0.0f;
bsdf->ior = 0.0f;
- ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
+ sd->flag |= bsdf_reflection_setup(bsdf);
}
}
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID) {
@@ -40,9 +40,9 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int t
bsdf->ior = eta;
if(refract)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
}
else {
bsdf->alpha_x = roughness;
@@ -50,9 +50,9 @@ ccl_device void svm_node_glass_setup(ShaderData *sd, MicrofacetBsdf *bsdf, int t
bsdf->ior = eta;
if(refract)
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
}
}
@@ -70,14 +70,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(mix_weight == 0.0f)
return;
- float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): ccl_fetch(sd, N);
+ float3 N = stack_valid(data_node.x)? stack_load_float3(stack, data_node.x): sd->N;
float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __uint_as_float(node.z);
float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
switch(type) {
case CLOSURE_BSDF_DIFFUSE_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
if(bsdf) {
@@ -86,31 +86,31 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
float roughness = param1;
if(roughness == 0.0f) {
- ccl_fetch(sd, flag) |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
+ sd->flag |= bsdf_diffuse_setup((DiffuseBsdf*)bsdf);
}
else {
bsdf->roughness = roughness;
- ccl_fetch(sd, flag) |= bsdf_oren_nayar_setup(bsdf);
+ sd->flag |= bsdf_oren_nayar_setup(bsdf);
}
}
break;
}
case CLOSURE_BSDF_TRANSLUCENT_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
if(bsdf) {
bsdf->N = N;
- ccl_fetch(sd, flag) |= bsdf_translucent_setup(bsdf);
+ sd->flag |= bsdf_translucent_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_TRANSPARENT_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
if(bsdf) {
- ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
+ sd->flag |= bsdf_transparent_setup(bsdf);
}
break;
}
@@ -123,7 +123,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(bsdf) {
@@ -135,21 +135,21 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
/* setup bsdf */
if(type == CLOSURE_BSDF_REFLECTION_ID)
- ccl_fetch(sd, flag) |= bsdf_reflection_setup(bsdf);
+ sd->flag |= bsdf_reflection_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.z));
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.z);
- ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf);
}
}
else
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_setup(bsdf);
+ sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
}
break;
@@ -161,7 +161,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(bsdf) {
@@ -169,7 +169,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->extra = NULL;
float eta = fmaxf(param2, 1e-5f);
- eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
/* setup bsdf */
if(type == CLOSURE_BSDF_REFRACTION_ID) {
@@ -177,7 +177,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->alpha_y = 0.0f;
bsdf->ior = eta;
- ccl_fetch(sd, flag) |= bsdf_refraction_setup(bsdf);
+ sd->flag |= bsdf_refraction_setup(bsdf);
}
else {
bsdf->alpha_x = param1;
@@ -185,9 +185,9 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->ior = eta;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID)
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
}
}
@@ -203,14 +203,14 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
}
#endif
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
/* index of refraction */
float eta = fmaxf(param2, 1e-5f);
- eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
/* fresnel */
- float cosNO = dot(N, ccl_fetch(sd, I));
+ float cosNO = dot(N, sd->I);
float fresnel = fresnel_dielectric_cos(cosNO, eta);
float roughness = param1;
@@ -249,7 +249,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && !kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
@@ -261,13 +261,13 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->alpha_x = param1;
bsdf->alpha_y = param1;
float eta = fmaxf(param2, 1e-5f);
- bsdf->ior = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
+ bsdf->ior = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
kernel_assert(stack_valid(data_node.z));
bsdf->extra->color = stack_load_float3(stack, data_node.z);
/* setup bsdf */
- ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf);
}
break;
@@ -280,7 +280,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE))
break;
#endif
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
if(bsdf) {
@@ -310,33 +310,33 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->ior = 0.0f;
if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID) {
- ccl_fetch(sd, flag) |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
+ sd->flag |= bsdf_microfacet_beckmann_aniso_setup(bsdf);
}
else if(type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID) {
- ccl_fetch(sd, flag) |= bsdf_microfacet_ggx_aniso_setup(bsdf);
+ sd->flag |= bsdf_microfacet_ggx_aniso_setup(bsdf);
}
else if(type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID) {
kernel_assert(stack_valid(data_node.w));
bsdf->extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
if(bsdf->extra) {
bsdf->extra->color = stack_load_float3(stack, data_node.w);
- ccl_fetch(sd, flag) |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
+ sd->flag |= bsdf_microfacet_multi_ggx_aniso_setup(bsdf);
}
}
else
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
+ sd->flag |= bsdf_ashikhmin_shirley_aniso_setup(bsdf);
}
break;
}
case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
VelvetBsdf *bsdf = (VelvetBsdf*)bsdf_alloc(sd, sizeof(VelvetBsdf), weight);
if(bsdf) {
bsdf->N = N;
bsdf->sigma = saturate(param1);
- ccl_fetch(sd, flag) |= bsdf_ashikhmin_velvet_setup(bsdf);
+ sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
}
break;
}
@@ -346,7 +346,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
break;
#endif
case CLOSURE_BSDF_DIFFUSE_TOON_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
ToonBsdf *bsdf = (ToonBsdf*)bsdf_alloc(sd, sizeof(ToonBsdf), weight);
if(bsdf) {
@@ -355,18 +355,18 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bsdf->smooth = param2;
if(type == CLOSURE_BSDF_DIFFUSE_TOON_ID)
- ccl_fetch(sd, flag) |= bsdf_diffuse_toon_setup(bsdf);
+ sd->flag |= bsdf_diffuse_toon_setup(bsdf);
else
- ccl_fetch(sd, flag) |= bsdf_glossy_toon_setup(bsdf);
+ sd->flag |= bsdf_glossy_toon_setup(bsdf);
}
break;
}
#ifdef __HAIR__
case CLOSURE_BSDF_HAIR_REFLECTION_ID:
case CLOSURE_BSDF_HAIR_TRANSMISSION_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
- if(ccl_fetch(sd, flag) & SD_BACKFACING && ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) {
+ if(sd->flag & SD_BACKFACING && sd->type & PRIMITIVE_ALL_CURVE) {
ShaderClosure *bsdf = bsdf_alloc(sd, sizeof(ShaderClosure), weight);
if(bsdf) {
@@ -376,7 +376,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
* better figure out a way to skip backfaces from rays
* spawned by transmission from the front */
bsdf->weight = make_float3(1.0f, 1.0f, 1.0f);
- ccl_fetch(sd, flag) |= bsdf_transparent_setup(bsdf);
+ sd->flag |= bsdf_transparent_setup(bsdf);
}
}
else {
@@ -390,18 +390,18 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
if(stack_valid(data_node.y)) {
bsdf->T = normalize(stack_load_float3(stack, data_node.y));
}
- else if(!(ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE)) {
- bsdf->T = normalize(ccl_fetch(sd, dPdv));
+ else if(!(sd->type & PRIMITIVE_ALL_CURVE)) {
+ bsdf->T = normalize(sd->dPdv);
bsdf->offset = 0.0f;
}
else
- bsdf->T = normalize(ccl_fetch(sd, dPdu));
+ bsdf->T = normalize(sd->dPdu);
if(type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
- ccl_fetch(sd, flag) |= bsdf_hair_reflection_setup(bsdf);
+ sd->flag |= bsdf_hair_reflection_setup(bsdf);
}
else {
- ccl_fetch(sd, flag) |= bsdf_hair_transmission_setup(bsdf);
+ sd->flag |= bsdf_hair_transmission_setup(bsdf);
}
}
}
@@ -414,8 +414,8 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
case CLOSURE_BSSRDF_CUBIC_ID:
case CLOSURE_BSSRDF_GAUSSIAN_ID:
case CLOSURE_BSSRDF_BURLEY_ID: {
- float3 albedo = ccl_fetch(sd, svm_closure_weight);
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight;
+ float3 albedo = sd->svm_closure_weight;
+ float3 weight = sd->svm_closure_weight * mix_weight;
float sample_weight = fabsf(average(weight));
/* disable in case of diffuse ancestor, can't see it well then and
@@ -441,7 +441,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->albedo = albedo.x;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, weight.y, 0.0f));
@@ -452,7 +452,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->albedo = albedo.y;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, weight.z));
@@ -463,7 +463,7 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
bssrdf->albedo = albedo.z;
bssrdf->sharpness = sharpness;
bssrdf->N = N;
- ccl_fetch(sd, flag) |= bssrdf_setup(bssrdf, (ClosureType)type);
+ sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
}
}
@@ -493,21 +493,21 @@ ccl_device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float
switch(type) {
case CLOSURE_VOLUME_ABSORPTION_ID: {
- float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - ccl_fetch(sd, svm_closure_weight)) * mix_weight * density;
+ float3 weight = (make_float3(1.0f, 1.0f, 1.0f) - sd->svm_closure_weight) * mix_weight * density;
ShaderClosure *sc = closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_NONE_ID, weight);
if(sc) {
- ccl_fetch(sd, flag) |= volume_absorption_setup(sc);
+ sd->flag |= volume_absorption_setup(sc);
}
break;
}
case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID: {
- float3 weight = ccl_fetch(sd, svm_closure_weight) * mix_weight * density;
+ float3 weight = sd->svm_closure_weight * mix_weight * density;
HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume*)bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
if(volume) {
volume->g = param2; /* g */
- ccl_fetch(sd, flag) |= volume_henyey_greenstein_setup(volume);
+ sd->flag |= volume_henyey_greenstein_setup(volume);
}
break;
}
@@ -527,12 +527,12 @@ ccl_device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 no
if(mix_weight == 0.0f)
return;
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, sd->svm_closure_weight * mix_weight);
}
else
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, ccl_fetch(sd, svm_closure_weight));
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_EMISSION_ID, sd->svm_closure_weight);
- ccl_fetch(sd, flag) |= SD_EMISSION;
+ sd->flag |= SD_EMISSION;
}
ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node)
@@ -545,10 +545,10 @@ ccl_device void svm_node_closure_background(ShaderData *sd, float *stack, uint4
if(mix_weight == 0.0f)
return;
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, sd->svm_closure_weight * mix_weight);
}
else
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, ccl_fetch(sd, svm_closure_weight));
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_BACKGROUND_ID, sd->svm_closure_weight);
}
ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node)
@@ -561,12 +561,12 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
if(mix_weight == 0.0f)
return;
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight * mix_weight);
}
else
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, ccl_fetch(sd, svm_closure_weight));
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, sd->svm_closure_weight);
- ccl_fetch(sd, flag) |= SD_HOLDOUT;
+ sd->flag |= SD_HOLDOUT;
}
ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
@@ -579,19 +579,19 @@ ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack,
if(mix_weight == 0.0f)
return;
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight) * mix_weight);
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight * mix_weight);
}
else
- closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, ccl_fetch(sd, svm_closure_weight));
+ closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight);
- ccl_fetch(sd, flag) |= SD_AO;
+ sd->flag |= SD_AO;
}
/* Closure Nodes */
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
{
- ccl_fetch(sd, svm_closure_weight) = weight;
+ sd->svm_closure_weight = weight;
}
ccl_device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b)
@@ -641,7 +641,7 @@ ccl_device void svm_node_mix_closure(ShaderData *sd, float *stack, uint4 node)
ccl_device void svm_node_set_normal(KernelGlobals *kg, ShaderData *sd, float *stack, uint in_direction, uint out_normal)
{
float3 normal = stack_load_float3(stack, in_direction);
- ccl_fetch(sd, N) = normal;
+ sd->N = normal;
stack_store_float3(stack, out_normal, normal);
}
diff --git a/intern/cycles/kernel/svm/svm_displace.h b/intern/cycles/kernel/svm/svm_displace.h
index 890ab41aaaa..c94fa130af7 100644
--- a/intern/cycles/kernel/svm/svm_displace.h
+++ b/intern/cycles/kernel/svm/svm_displace.h
@@ -25,10 +25,10 @@ ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stac
uint normal_offset, distance_offset, invert, use_object_space;
decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, &use_object_space);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
+ float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
- float3 dPdx = ccl_fetch(sd, dP).dx;
- float3 dPdy = ccl_fetch(sd, dP).dy;
+ float3 dPdx = sd->dP.dx;
+ float3 dPdy = sd->dP.dy;
if(use_object_space) {
object_inverse_normal_transform(kg, sd, &normal_in);
@@ -80,14 +80,14 @@ ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, flo
{
float d = stack_load_float(stack, fac_offset);
- float3 dP = ccl_fetch(sd, N);
+ float3 dP = sd->N;
object_inverse_normal_transform(kg, sd, &dP);
dP *= d*0.1f; /* todo: get rid of this factor */
object_dir_transform(kg, sd, &dP);
- ccl_fetch(sd, P) += dP;
+ sd->P += dP;
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_fresnel.h b/intern/cycles/kernel/svm/svm_fresnel.h
index 23c97d80cb0..3703ec55015 100644
--- a/intern/cycles/kernel/svm/svm_fresnel.h
+++ b/intern/cycles/kernel/svm/svm_fresnel.h
@@ -23,12 +23,12 @@ ccl_device void svm_node_fresnel(ShaderData *sd, float *stack, uint ior_offset,
uint normal_offset, out_offset;
decode_node_uchar4(node, &normal_offset, &out_offset, NULL, NULL);
float eta = (stack_valid(ior_offset))? stack_load_float(stack, ior_offset): __uint_as_float(ior_value);
- float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
+ float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
eta = fmaxf(eta, 1e-5f);
- eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f/eta: eta;
+ eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta;
- float f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta);
+ float f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
stack_store_float(stack, out_offset, f);
}
@@ -44,18 +44,18 @@ ccl_device void svm_node_layer_weight(ShaderData *sd, float *stack, uint4 node)
decode_node_uchar4(node.w, &type, &normal_offset, &out_offset, NULL);
float blend = (stack_valid(blend_offset))? stack_load_float(stack, blend_offset): __uint_as_float(blend_value);
- float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): ccl_fetch(sd, N);
+ float3 normal_in = (stack_valid(normal_offset))? stack_load_float3(stack, normal_offset): sd->N;
float f;
if(type == NODE_LAYER_WEIGHT_FRESNEL) {
float eta = fmaxf(1.0f - blend, 1e-5f);
- eta = (ccl_fetch(sd, flag) & SD_BACKFACING)? eta: 1.0f/eta;
+ eta = (sd->flag & SD_BACKFACING)? eta: 1.0f/eta;
- f = fresnel_dielectric_cos(dot(ccl_fetch(sd, I), normal_in), eta);
+ f = fresnel_dielectric_cos(dot(sd->I, normal_in), eta);
}
else {
- f = fabsf(dot(ccl_fetch(sd, I), normal_in));
+ f = fabsf(dot(sd->I, normal_in));
if(blend != 0.5f) {
blend = clamp(blend, 0.0f, 1.0f-1e-5f);
diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h
index 7d512f7ff4d..4a09d9f6653 100644
--- a/intern/cycles/kernel/svm/svm_geometry.h
+++ b/intern/cycles/kernel/svm/svm_geometry.h
@@ -27,15 +27,15 @@ ccl_device_inline void svm_node_geometry(KernelGlobals *kg,
float3 data;
switch(type) {
- case NODE_GEOM_P: data = ccl_fetch(sd, P); break;
- case NODE_GEOM_N: data = ccl_fetch(sd, N); break;
+ case NODE_GEOM_P: data = sd->P; break;
+ case NODE_GEOM_N: data = sd->N; break;
#ifdef __DPDU__
case NODE_GEOM_T: data = primitive_tangent(kg, sd); break;
#endif
- case NODE_GEOM_I: data = ccl_fetch(sd, I); break;
- case NODE_GEOM_Ng: data = ccl_fetch(sd, Ng); break;
+ case NODE_GEOM_I: data = sd->I; break;
+ case NODE_GEOM_Ng: data = sd->Ng; break;
#ifdef __UV__
- case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u), ccl_fetch(sd, v), 0.0f); break;
+ case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break;
#endif
}
@@ -48,8 +48,8 @@ ccl_device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, flo
float3 data;
switch(type) {
- case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx; break;
- case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dx, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dx, 0.0f); break;
+ case NODE_GEOM_P: data = sd->P + sd->dP.dx; break;
+ case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break;
default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
}
@@ -65,8 +65,8 @@ ccl_device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, flo
float3 data;
switch(type) {
- case NODE_GEOM_P: data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy; break;
- case NODE_GEOM_uv: data = make_float3(ccl_fetch(sd, u) + ccl_fetch(sd, du).dy, ccl_fetch(sd, v) + ccl_fetch(sd, dv).dy, 0.0f); break;
+ case NODE_GEOM_P: data = sd->P + sd->dP.dy; break;
+ case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break;
default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
}
@@ -87,9 +87,9 @@ ccl_device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *s
stack_store_float3(stack, out_offset, object_location(kg, sd));
return;
}
- case NODE_INFO_OB_INDEX: data = object_pass_id(kg, ccl_fetch(sd, object)); break;
+ case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
- case NODE_INFO_OB_RANDOM: data = object_random_number(kg, ccl_fetch(sd, object)); break;
+ case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
default: data = 0.0f; break;
}
@@ -106,44 +106,44 @@ ccl_device void svm_node_particle_info(KernelGlobals *kg,
{
switch(type) {
case NODE_INFO_PAR_INDEX: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float(stack, out_offset, particle_index(kg, particle_id));
break;
}
case NODE_INFO_PAR_AGE: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float(stack, out_offset, particle_age(kg, particle_id));
break;
}
case NODE_INFO_PAR_LIFETIME: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
break;
}
case NODE_INFO_PAR_LOCATION: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
break;
}
#if 0 /* XXX float4 currently not supported in SVM stack */
case NODE_INFO_PAR_ROTATION: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
break;
}
#endif
case NODE_INFO_PAR_SIZE: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float(stack, out_offset, particle_size(kg, particle_id));
break;
}
case NODE_INFO_PAR_VELOCITY: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
break;
}
case NODE_INFO_PAR_ANGULAR_VELOCITY: {
- int particle_id = object_particle_id(kg, ccl_fetch(sd, object));
+ int particle_id = object_particle_id(kg, sd->object);
stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
break;
}
@@ -165,7 +165,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg,
switch(type) {
case NODE_INFO_CURVE_IS_STRAND: {
- data = (ccl_fetch(sd, type) & PRIMITIVE_ALL_CURVE) != 0;
+ data = (sd->type & PRIMITIVE_ALL_CURVE) != 0;
stack_store_float(stack, out_offset, data);
break;
}
@@ -177,7 +177,7 @@ ccl_device void svm_node_hair_info(KernelGlobals *kg,
break;
}
/*case NODE_INFO_CURVE_FADE: {
- data = ccl_fetch(sd, curve_transparency);
+ data = sd->curve_transparency;
stack_store_float(stack, out_offset, data);
break;
}*/
diff --git a/intern/cycles/kernel/svm/svm_image.h b/intern/cycles/kernel/svm/svm_image.h
index 2afdf61b476..76acc9253a1 100644
--- a/intern/cycles/kernel/svm/svm_image.h
+++ b/intern/cycles/kernel/svm/svm_image.h
@@ -144,7 +144,6 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
case 86: r = kernel_tex_image_interp(__tex_image_byte4_086, x, y); break;
case 87: r = kernel_tex_image_interp(__tex_image_byte4_087, x, y); break;
case 88: r = kernel_tex_image_interp(__tex_image_byte4_088, x, y); break;
- case 89: r = kernel_tex_image_interp(__tex_image_byte4_089, x, y); break;
default:
kernel_assert(0);
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
@@ -238,9 +237,9 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
ccl_device void svm_node_tex_image_box(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
{
/* get object space normal */
- float3 N = ccl_fetch(sd, N);
+ float3 N = sd->N;
- N = ccl_fetch(sd, N);
+ N = sd->N;
object_inverse_normal_transform(kg, sd, &N);
/* project from direction vector to barycentric coordinates in triangles */
diff --git a/intern/cycles/kernel/svm/svm_light_path.h b/intern/cycles/kernel/svm/svm_light_path.h
index 04f6f623f18..1492e358608 100644
--- a/intern/cycles/kernel/svm/svm_light_path.h
+++ b/intern/cycles/kernel/svm/svm_light_path.h
@@ -31,8 +31,8 @@ ccl_device void svm_node_light_path(ShaderData *sd, ccl_addr_space PathState *st
case NODE_LP_reflection: info = (path_flag & PATH_RAY_REFLECT)? 1.0f: 0.0f; break;
case NODE_LP_transmission: info = (path_flag & PATH_RAY_TRANSMIT)? 1.0f: 0.0f; break;
case NODE_LP_volume_scatter: info = (path_flag & PATH_RAY_VOLUME_SCATTER)? 1.0f: 0.0f; break;
- case NODE_LP_backfacing: info = (ccl_fetch(sd, flag) & SD_BACKFACING)? 1.0f: 0.0f; break;
- case NODE_LP_ray_length: info = ccl_fetch(sd, ray_length); break;
+ case NODE_LP_backfacing: info = (sd->flag & SD_BACKFACING)? 1.0f: 0.0f; break;
+ case NODE_LP_ray_length: info = sd->ray_length; break;
case NODE_LP_ray_depth: info = (float)state->bounce; break;
case NODE_LP_ray_diffuse: info = (float)state->diffuse_bounce; break;
case NODE_LP_ray_glossy: info = (float)state->glossy_bounce; break;
@@ -56,14 +56,14 @@ ccl_device void svm_node_light_falloff(ShaderData *sd, float *stack, uint4 node)
switch(type) {
case NODE_LIGHT_FALLOFF_QUADRATIC: break;
- case NODE_LIGHT_FALLOFF_LINEAR: strength *= ccl_fetch(sd, ray_length); break;
- case NODE_LIGHT_FALLOFF_CONSTANT: strength *= ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length); break;
+ case NODE_LIGHT_FALLOFF_LINEAR: strength *= sd->ray_length; break;
+ case NODE_LIGHT_FALLOFF_CONSTANT: strength *= sd->ray_length*sd->ray_length; break;
}
float smooth = stack_load_float(stack, smooth_offset);
if(smooth > 0.0f) {
- float squared = ccl_fetch(sd, ray_length)*ccl_fetch(sd, ray_length);
+ float squared = sd->ray_length*sd->ray_length;
/* Distant lamps set the ray length to FLT_MAX, which causes squared to overflow. */
if(isfinite(squared)) {
strength *= squared/(smooth + squared);
diff --git a/intern/cycles/kernel/svm/svm_noisetex.h b/intern/cycles/kernel/svm/svm_noisetex.h
index 62ff38cf1c5..0347ab7b193 100644
--- a/intern/cycles/kernel/svm/svm_noisetex.h
+++ b/intern/cycles/kernel/svm/svm_noisetex.h
@@ -18,50 +18,42 @@ CCL_NAMESPACE_BEGIN
/* Noise */
-ccl_device_inline void svm_noise(float3 p, float detail, float distortion, float *fac, float3 *color)
-{
- int hard = 0;
-
- if(distortion != 0.0f) {
- float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
-
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
-
- p += r;
- }
-
- *fac = noise_turbulence(p, detail, hard);
- *color = make_float3(*fac,
- noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
- noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
-}
-
ccl_device void svm_node_tex_noise(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
{
uint co_offset, scale_offset, detail_offset, distortion_offset, fac_offset, color_offset;
decode_node_uchar4(node.y, &co_offset, &scale_offset, &detail_offset, &distortion_offset);
+ decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
uint4 node2 = read_node(kg, offset);
float scale = stack_load_float_default(stack, scale_offset, node2.x);
float detail = stack_load_float_default(stack, detail_offset, node2.y);
float distortion = stack_load_float_default(stack, distortion_offset, node2.z);
- float3 co = stack_load_float3(stack, co_offset);
+ float3 p = stack_load_float3(stack, co_offset) * scale;
+ int hard = 0;
- float3 color;
- float f;
+ if(distortion != 0.0f) {
+ float3 r, offset = make_float3(13.5f, 13.5f, 13.5f);
+
+ r.x = noise(p + offset) * distortion;
+ r.y = noise(p) * distortion;
+ r.z = noise(p - offset) * distortion;
- svm_noise(co*scale, detail, distortion, &f, &color);
+ p += r;
+ }
- decode_node_uchar4(node.z, &color_offset, &fac_offset, NULL, NULL);
+ float f = noise_turbulence(p, detail, hard);
- if(stack_valid(fac_offset))
+ if(stack_valid(fac_offset)) {
stack_store_float(stack, fac_offset, f);
- if(stack_valid(color_offset))
+ }
+ if(stack_valid(color_offset)) {
+ float3 color = make_float3(f,
+ noise_turbulence(make_float3(p.y, p.x, p.z), detail, hard),
+ noise_turbulence(make_float3(p.y, p.z, p.x), detail, hard));
stack_store_float3(stack, color_offset, color);
+ }
}
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h
index c0b01262212..c94327401f5 100644
--- a/intern/cycles/kernel/svm/svm_tex_coord.h
+++ b/intern/cycles/kernel/svm/svm_tex_coord.h
@@ -31,9 +31,9 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg,
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = ccl_fetch(sd, P);
+ data = sd->P;
if(node.w == 0) {
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ if(sd->object != OBJECT_NONE) {
object_inverse_position_transform(kg, sd, &data);
}
}
@@ -48,47 +48,47 @@ ccl_device void svm_node_tex_coord(KernelGlobals *kg,
break;
}
case NODE_TEXCO_NORMAL: {
- data = ccl_fetch(sd, N);
+ data = sd->N;
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = transform_point(&tfm, ccl_fetch(sd, P));
+ if(sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P);
else
- data = transform_point(&tfm, ccl_fetch(sd, P) + camera_position(kg));
+ data = transform_point(&tfm, sd->P + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P));
+ if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P);
else
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P));
+ data = camera_world_to_ndc(kg, sd, sd->P);
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
+ if(sd->object != OBJECT_NONE)
+ data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
else
- data = ccl_fetch(sd, I);
+ data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, ccl_fetch(sd, object));
+ data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, ccl_fetch(sd, object));
+ data = object_dupli_uv(kg, sd->object);
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = ccl_fetch(sd, P);
+ data = sd->P;
#ifdef __VOLUME__
- if(ccl_fetch(sd, object) != OBJECT_NONE)
+ if(sd->object != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -112,9 +112,9 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
+ data = sd->P + sd->dP.dx;
if(node.w == 0) {
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ if(sd->object != OBJECT_NONE) {
object_inverse_position_transform(kg, sd, &data);
}
}
@@ -129,47 +129,47 @@ ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
break;
}
case NODE_TEXCO_NORMAL: {
- data = ccl_fetch(sd, N);
+ data = sd->N;
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
+ if(sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P + sd->dP.dx);
else
- data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx + camera_position(kg));
+ data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dx);
+ if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
else
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
+ data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
+ if(sd->object != OBJECT_NONE)
+ data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
else
- data = ccl_fetch(sd, I);
+ data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, ccl_fetch(sd, object));
+ data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, ccl_fetch(sd, object));
+ data = object_dupli_uv(kg, sd->object);
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
+ data = sd->P + sd->dP.dx;
#ifdef __VOLUME__
- if(ccl_fetch(sd, object) != OBJECT_NONE)
+ if(sd->object != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -196,9 +196,9 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
switch(type) {
case NODE_TEXCO_OBJECT: {
- data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
+ data = sd->P + sd->dP.dy;
if(node.w == 0) {
- if(ccl_fetch(sd, object) != OBJECT_NONE) {
+ if(sd->object != OBJECT_NONE) {
object_inverse_position_transform(kg, sd, &data);
}
}
@@ -213,47 +213,47 @@ ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
break;
}
case NODE_TEXCO_NORMAL: {
- data = ccl_fetch(sd, N);
+ data = sd->N;
object_inverse_normal_transform(kg, sd, &data);
break;
}
case NODE_TEXCO_CAMERA: {
Transform tfm = kernel_data.cam.worldtocamera;
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
+ if(sd->object != OBJECT_NONE)
+ data = transform_point(&tfm, sd->P + sd->dP.dy);
else
- data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy + camera_position(kg));
+ data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
break;
}
case NODE_TEXCO_WINDOW: {
- if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dy);
+ if((path_flag & PATH_RAY_CAMERA) && sd->object == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
+ data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
else
- data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
+ data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
data.z = 0.0f;
break;
}
case NODE_TEXCO_REFLECTION: {
- if(ccl_fetch(sd, object) != OBJECT_NONE)
- data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
+ if(sd->object != OBJECT_NONE)
+ data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
else
- data = ccl_fetch(sd, I);
+ data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
- data = object_dupli_generated(kg, ccl_fetch(sd, object));
+ data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
- data = object_dupli_uv(kg, ccl_fetch(sd, object));
+ data = object_dupli_uv(kg, sd->object);
break;
}
case NODE_TEXCO_VOLUME_GENERATED: {
- data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
+ data = sd->P + sd->dP.dy;
#ifdef __VOLUME__
- if(ccl_fetch(sd, object) != OBJECT_NONE)
+ if(sd->object != OBJECT_NONE)
data = volume_normalized_position(kg, sd, data);
#endif
break;
@@ -274,12 +274,12 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
float3 color = stack_load_float3(stack, color_offset);
color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
- bool is_backfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) != 0;
+ bool is_backfacing = (sd->flag & SD_BACKFACING) != 0;
float3 N;
if(space == NODE_NORMAL_MAP_TANGENT) {
/* tangent space */
- if(ccl_fetch(sd, object) == OBJECT_NONE) {
+ if(sd->object == OBJECT_NONE) {
stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
return;
}
@@ -299,11 +299,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
float sign = primitive_attribute_float(kg, sd, attr_sign, NULL, NULL);
float3 normal;
- if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
+ if(sd->shader & SHADER_SMOOTH_NORMAL) {
normal = primitive_attribute_float3(kg, sd, attr_normal, NULL, NULL);
}
else {
- normal = ccl_fetch(sd, Ng);
+ normal = sd->Ng;
/* the normal is already inverted, which is too soon for the math here */
if(is_backfacing) {
@@ -345,11 +345,11 @@ ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *st
if(strength != 1.0f) {
strength = max(strength, 0.0f);
- N = safe_normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
+ N = safe_normalize(sd->N + (N - sd->N)*strength);
}
if(is_zero(N)) {
- N = ccl_fetch(sd, N);
+ N = sd->N;
}
stack_store_float3(stack, normal_offset, N);
@@ -377,7 +377,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
float3 generated;
if(desc.offset == ATTR_STD_NOT_FOUND)
- generated = ccl_fetch(sd, P);
+ generated = sd->P;
else
generated = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
@@ -390,7 +390,7 @@ ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack
}
object_normal_transform(kg, sd, &tangent);
- tangent = cross(ccl_fetch(sd, N), normalize(cross(tangent, ccl_fetch(sd, N))));
+ tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
stack_store_float3(stack, tangent_offset, tangent);
}
diff --git a/intern/cycles/kernel/svm/svm_vector_transform.h b/intern/cycles/kernel/svm/svm_vector_transform.h
index 4c32130d06d..4e92f27acdb 100644
--- a/intern/cycles/kernel/svm/svm_vector_transform.h
+++ b/intern/cycles/kernel/svm/svm_vector_transform.h
@@ -33,7 +33,7 @@ ccl_device void svm_node_vector_transform(KernelGlobals *kg, ShaderData *sd, flo
NodeVectorTransformConvertSpace to = (NodeVectorTransformConvertSpace)ito;
Transform tfm;
- bool is_object = (ccl_fetch(sd, object) != OBJECT_NONE);
+ bool is_object = (sd->object != OBJECT_NONE);
bool is_direction = (type == NODE_VECTOR_TRANSFORM_TYPE_VECTOR || type == NODE_VECTOR_TRANSFORM_TYPE_NORMAL);
/* From world */
diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h
index a8b3604a8a7..9e826c8c23f 100644
--- a/intern/cycles/kernel/svm/svm_voxel.h
+++ b/intern/cycles/kernel/svm/svm_voxel.h
@@ -46,7 +46,7 @@ ccl_device void svm_node_tex_voxel(KernelGlobals *kg,
# if defined(__KERNEL_CUDA__)
# if __CUDA_ARCH__ >= 300
CUtexObject tex = kernel_tex_fetch(__bindless_mapping, id);
- if(id < 2048) /* TODO(dingto): Make this a variable */
+ if(id < TEX_START_HALF4_CUDA_KEPLER)
r = kernel_tex_image_interp_3d_float4(tex, co.x, co.y, co.z);
else {
float f = kernel_tex_image_interp_3d_float(tex, co.x, co.y, co.z);
diff --git a/intern/cycles/kernel/svm/svm_wireframe.h b/intern/cycles/kernel/svm/svm_wireframe.h
index 87e40791333..3c6353c8001 100644
--- a/intern/cycles/kernel/svm/svm_wireframe.h
+++ b/intern/cycles/kernel/svm/svm_wireframe.h
@@ -41,9 +41,9 @@ ccl_device_inline float wireframe(KernelGlobals *kg,
float3 *P)
{
#ifdef __HAIR__
- if(ccl_fetch(sd, prim) != PRIM_NONE && ccl_fetch(sd, type) & PRIMITIVE_ALL_TRIANGLE)
+ if(sd->prim != PRIM_NONE && sd->type & PRIMITIVE_ALL_TRIANGLE)
#else
- if(ccl_fetch(sd, prim) != PRIM_NONE)
+ if(sd->prim != PRIM_NONE)
#endif
{
float3 Co[3];
@@ -52,12 +52,12 @@ ccl_device_inline float wireframe(KernelGlobals *kg,
/* Triangles */
int np = 3;
- if(ccl_fetch(sd, type) & PRIMITIVE_TRIANGLE)
- triangle_vertices(kg, ccl_fetch(sd, prim), Co);
+ if(sd->type & PRIMITIVE_TRIANGLE)
+ triangle_vertices(kg, sd->prim, Co);
else
- motion_triangle_vertices(kg, ccl_fetch(sd, object), ccl_fetch(sd, prim), ccl_fetch(sd, time), Co);
+ motion_triangle_vertices(kg, sd->object, sd->prim, sd->time, Co);
- if(!(ccl_fetch(sd, object_flag) & SD_OBJECT_TRANSFORM_APPLIED)) {
+ if(!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
object_position_transform(kg, sd, &Co[0]);
object_position_transform(kg, sd, &Co[1]);
object_position_transform(kg, sd, &Co[2]);
@@ -66,8 +66,8 @@ ccl_device_inline float wireframe(KernelGlobals *kg,
if(pixel_size) {
// Project the derivatives of P to the viewing plane defined
// by I so we have a measure of how big is a pixel at this point
- float pixelwidth_x = len(ccl_fetch(sd, dP).dx - dot(ccl_fetch(sd, dP).dx, ccl_fetch(sd, I)) * ccl_fetch(sd, I));
- float pixelwidth_y = len(ccl_fetch(sd, dP).dy - dot(ccl_fetch(sd, dP).dy, ccl_fetch(sd, I)) * ccl_fetch(sd, I));
+ float pixelwidth_x = len(sd->dP.dx - dot(sd->dP.dx, sd->I) * sd->I);
+ float pixelwidth_y = len(sd->dP.dy - dot(sd->dP.dy, sd->I) * sd->I);
// Take the average of both axis' length
pixelwidth = (pixelwidth_x + pixelwidth_y) * 0.5f;
}
@@ -113,20 +113,20 @@ ccl_device void svm_node_wireframe(KernelGlobals *kg,
* With OpenCL 2.0 it's possible to avoid this change, but for until
* then we'll be living with such an exception.
*/
- float3 P = ccl_fetch(sd, P);
+ float3 P = sd->P;
float f = wireframe(kg, sd, size, pixel_size, &P);
#else
- float f = wireframe(kg, sd, size, pixel_size, &ccl_fetch(sd, P));
+ float f = wireframe(kg, sd, size, pixel_size, &sd->P);
#endif
/* TODO(sergey): Think of faster way to calculate derivatives. */
if(bump_offset == NODE_BUMP_OFFSET_DX) {
- float3 Px = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dx;
- f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(ccl_fetch(sd, dP).dx);
+ float3 Px = sd->P - sd->dP.dx;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Px)) / len(sd->dP.dx);
}
else if(bump_offset == NODE_BUMP_OFFSET_DY) {
- float3 Py = ccl_fetch(sd, P) - ccl_fetch(sd, dP).dy;
- f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(ccl_fetch(sd, dP).dy);
+ float3 Py = sd->P - sd->dP.dy;
+ f += (f - wireframe(kg, sd, size, pixel_size, &Py)) / len(sd->dP.dy);
}
if(stack_valid(out_fac))
diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt
index 8eaa9de3874..17ac66644e2 100644
--- a/intern/cycles/render/CMakeLists.txt
+++ b/intern/cycles/render/CMakeLists.txt
@@ -1,14 +1,6 @@
set(INC
- .
- ../device
- ../graph
- ../kernel
- ../kernel/svm
- ../kernel/osl
- ../bvh
- ../subd
- ../util
+ ..
../../glew-mx
)
diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp
index c0d429a583c..e157a385904 100644
--- a/intern/cycles/render/attribute.cpp
+++ b/intern/cycles/render/attribute.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include "image.h"
-#include "mesh.h"
-#include "attribute.h"
+#include "render/image.h"
+#include "render/mesh.h"
+#include "render/attribute.h"
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_transform.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/attribute.h b/intern/cycles/render/attribute.h
index f4538c76369..a64eb6542d5 100644
--- a/intern/cycles/render/attribute.h
+++ b/intern/cycles/render/attribute.h
@@ -17,12 +17,12 @@
#ifndef __ATTRIBUTE_H__
#define __ATTRIBUTE_H__
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "util_list.h"
-#include "util_param.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_list.h"
+#include "util/util_param.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/background.cpp b/intern/cycles/render/background.cpp
index 8d7d7b847fd..930debe1e33 100644
--- a/intern/cycles/render/background.cpp
+++ b/intern/cycles/render/background.cpp
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-#include "background.h"
-#include "device.h"
-#include "integrator.h"
-#include "graph.h"
-#include "nodes.h"
-#include "scene.h"
-#include "shader.h"
-
-#include "util_foreach.h"
-#include "util_math.h"
-#include "util_types.h"
+#include "render/background.h"
+#include "device/device.h"
+#include "render/integrator.h"
+#include "render/graph.h"
+#include "render/nodes.h"
+#include "render/scene.h"
+#include "render/shader.h"
+
+#include "util/util_foreach.h"
+#include "util/util_math.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/background.h b/intern/cycles/render/background.h
index 8029c6a9e80..db20b6ebf87 100644
--- a/intern/cycles/render/background.h
+++ b/intern/cycles/render/background.h
@@ -17,9 +17,9 @@
#ifndef __BACKGROUND_H__
#define __BACKGROUND_H__
-#include "node.h"
+#include "graph/node.h"
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -30,7 +30,7 @@ class Shader;
class Background : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
float ao_factor;
float ao_distance;
diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp
index d9a297002c6..c0fcd517390 100644
--- a/intern/cycles/render/bake.cpp
+++ b/intern/cycles/render/bake.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "bake.h"
-#include "integrator.h"
+#include "render/bake.h"
+#include "render/integrator.h"
CCL_NAMESPACE_BEGIN
@@ -171,9 +171,9 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre
/* needs to be up to data for attribute access */
device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
- device->mem_alloc(d_input, MEM_READ_ONLY);
+ device->mem_alloc("bake_input", d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_READ_WRITE);
+ device->mem_alloc("bake_output", d_output, MEM_READ_WRITE);
DeviceTask task(DeviceTask::SHADER);
task.shader_input = d_input.device_pointer;
diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h
index 25f5eb3c897..ceb94cfb682 100644
--- a/intern/cycles/render/bake.h
+++ b/intern/cycles/render/bake.h
@@ -17,11 +17,11 @@
#ifndef __BAKE_H__
#define __BAKE_H__
-#include "device.h"
-#include "scene.h"
+#include "device/device.h"
+#include "render/scene.h"
-#include "util_progress.h"
-#include "util_vector.h"
+#include "util/util_progress.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -73,7 +73,7 @@ public:
bool need_update;
- int total_pixel_samples;
+ size_t total_pixel_samples;
private:
BakeData *m_bake_data;
diff --git a/intern/cycles/render/buffers.cpp b/intern/cycles/render/buffers.cpp
index f1692712d61..fe2c2e78926 100644
--- a/intern/cycles/render/buffers.cpp
+++ b/intern/cycles/render/buffers.cpp
@@ -16,17 +16,17 @@
#include <stdlib.h>
-#include "buffers.h"
-#include "device.h"
-
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_hash.h"
-#include "util_image.h"
-#include "util_math.h"
-#include "util_opengl.h"
-#include "util_time.h"
-#include "util_types.h"
+#include "render/buffers.h"
+#include "device/device.h"
+
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_hash.h"
+#include "util/util_image.h"
+#include "util/util_math.h"
+#include "util/util_opengl.h"
+#include "util/util_time.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -129,13 +129,13 @@ void RenderBuffers::reset(Device *device, BufferParams& params_)
/* allocate buffer */
buffer.resize(params.width*params.height*params.get_passes_size());
- device->mem_alloc(buffer, MEM_READ_WRITE);
+ device->mem_alloc("render_buffer", buffer, MEM_READ_WRITE);
device->mem_zero(buffer);
/* allocate rng state */
rng_state.resize(params.width, params.height);
- device->mem_alloc(rng_state, MEM_READ_WRITE);
+ device->mem_alloc("rng_state", rng_state, MEM_READ_WRITE);
}
bool RenderBuffers::copy_from_device()
diff --git a/intern/cycles/render/buffers.h b/intern/cycles/render/buffers.h
index c9c2a21079a..5c78971678a 100644
--- a/intern/cycles/render/buffers.h
+++ b/intern/cycles/render/buffers.h
@@ -17,16 +17,16 @@
#ifndef __BUFFERS_H__
#define __BUFFERS_H__
-#include "device_memory.h"
+#include "device/device_memory.h"
-#include "film.h"
+#include "render/film.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "util_half.h"
-#include "util_string.h"
-#include "util_thread.h"
-#include "util_types.h"
+#include "util/util_half.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp
index c8c51ec96d2..83ff8a10618 100644
--- a/intern/cycles/render/camera.cpp
+++ b/intern/cycles/render/camera.cpp
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "tables.h"
-
-#include "device.h"
-
-#include "util_foreach.h"
-#include "util_function.h"
-#include "util_math_cdf.h"
-#include "util_vector.h"
+#include "render/camera.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/tables.h"
+
+#include "device/device.h"
+
+#include "util/util_foreach.h"
+#include "util/util_function.h"
+#include "util/util_math_cdf.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h
index 141ef9cccef..dd6b831b347 100644
--- a/intern/cycles/render/camera.h
+++ b/intern/cycles/render/camera.h
@@ -17,13 +17,13 @@
#ifndef __CAMERA_H__
#define __CAMERA_H__
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "node.h"
+#include "graph/node.h"
-#include "util_boundbox.h"
-#include "util_transform.h"
-#include "util_types.h"
+#include "util/util_boundbox.h"
+#include "util/util_transform.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -39,7 +39,7 @@ class Scene;
class Camera : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
/* Specifies an offset for the shutter's time interval. */
enum MotionPosition {
diff --git a/intern/cycles/render/constant_fold.cpp b/intern/cycles/render/constant_fold.cpp
index b7f25663bc3..2569d9eec27 100644
--- a/intern/cycles/render/constant_fold.cpp
+++ b/intern/cycles/render/constant_fold.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "constant_fold.h"
-#include "graph.h"
+#include "render/constant_fold.h"
+#include "render/graph.h"
-#include "util_foreach.h"
-#include "util_logging.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/constant_fold.h b/intern/cycles/render/constant_fold.h
index 7962698319f..33f93b8c0ab 100644
--- a/intern/cycles/render/constant_fold.h
+++ b/intern/cycles/render/constant_fold.h
@@ -17,8 +17,8 @@
#ifndef __CONSTANT_FOLD_H__
#define __CONSTANT_FOLD_H__
-#include "util_types.h"
-#include "svm_types.h"
+#include "util/util_types.h"
+#include "kernel/svm/svm_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/curves.cpp b/intern/cycles/render/curves.cpp
index f671eb19cae..4c085b928fb 100644
--- a/intern/cycles/render/curves.cpp
+++ b/intern/cycles/render/curves.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "device.h"
-#include "curves.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-
-#include "util_foreach.h"
-#include "util_map.h"
-#include "util_progress.h"
-#include "util_vector.h"
+#include "device/device.h"
+#include "render/curves.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+
+#include "util/util_foreach.h"
+#include "util/util_map.h"
+#include "util/util_progress.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/curves.h b/intern/cycles/render/curves.h
index e41967eebf5..8834764bd63 100644
--- a/intern/cycles/render/curves.h
+++ b/intern/cycles/render/curves.h
@@ -17,8 +17,8 @@
#ifndef __CURVES_H__
#define __CURVES_H__
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp
index 923252bb375..7809f4345f1 100644
--- a/intern/cycles/render/film.cpp
+++ b/intern/cycles/render/film.cpp
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "device.h"
-#include "film.h"
-#include "integrator.h"
-#include "mesh.h"
-#include "scene.h"
-#include "tables.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_math.h"
-#include "util_math_cdf.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/film.h"
+#include "render/integrator.h"
+#include "render/mesh.h"
+#include "render/scene.h"
+#include "render/tables.h"
+
+#include "util/util_algorithm.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_math.h"
+#include "util/util_math_cdf.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h
index 9fa51c51f52..83c941d5c57 100644
--- a/intern/cycles/render/film.h
+++ b/intern/cycles/render/film.h
@@ -17,12 +17,12 @@
#ifndef __FILM_H__
#define __FILM_H__
-#include "util_string.h"
-#include "util_vector.h"
+#include "util/util_string.h"
+#include "util/util_vector.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "node.h"
+#include "graph/node.h"
CCL_NAMESPACE_BEGIN
@@ -53,7 +53,7 @@ public:
class Film : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
float exposure;
array<Pass> passes;
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index f6c83fb5c7e..12fff8e5587 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -14,17 +14,18 @@
* limitations under the License.
*/
-#include "attribute.h"
-#include "graph.h"
-#include "nodes.h"
-#include "shader.h"
-#include "constant_fold.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_queue.h"
-#include "util_logging.h"
+#include "render/attribute.h"
+#include "render/graph.h"
+#include "render/nodes.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/constant_fold.h"
+
+#include "util/util_algorithm.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_queue.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -195,6 +196,7 @@ bool ShaderNode::equals(const ShaderNode& other)
ShaderGraph::ShaderGraph()
{
finalized = false;
+ simplified = false;
num_node_ids = 0;
add(new OutputNode());
}
@@ -207,6 +209,8 @@ ShaderGraph::~ShaderGraph()
ShaderNode *ShaderGraph::add(ShaderNode *node)
{
assert(!finalized);
+ simplified = false;
+
node->id = num_node_ids++;
nodes.push_back(node);
return node;
@@ -234,6 +238,8 @@ ShaderGraph *ShaderGraph::copy()
foreach(ShaderNode *node, nodes)
newgraph->add(nodes_copy[node]);
+ newgraph->simplified = simplified;
+
return newgraph;
}
@@ -273,6 +279,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
void ShaderGraph::disconnect(ShaderOutput *from)
{
assert(!finalized);
+ simplified = false;
foreach(ShaderInput *sock, from->links) {
sock->link = NULL;
@@ -285,6 +292,7 @@ void ShaderGraph::disconnect(ShaderInput *to)
{
assert(!finalized);
assert(to->link);
+ simplified = false;
ShaderOutput *from = to->link;
@@ -294,6 +302,8 @@ void ShaderGraph::disconnect(ShaderInput *to)
void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
{
+ simplified = false;
+
/* Copy because disconnect modifies this list */
vector<ShaderInput*> outputs = from->links;
@@ -310,9 +320,19 @@ void ShaderGraph::relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to)
}
}
+void ShaderGraph::simplify(Scene *scene)
+{
+ if(!simplified) {
+ default_inputs(scene->shader_manager->use_osl());
+ clean(scene);
+ refine_bump_nodes();
+
+ simplified = true;
+ }
+}
+
void ShaderGraph::finalize(Scene *scene,
bool do_bump,
- bool do_osl,
bool do_simplify,
bool bump_in_object_space)
{
@@ -322,9 +342,7 @@ void ShaderGraph::finalize(Scene *scene,
* modified afterwards. */
if(!finalized) {
- default_inputs(do_osl);
- clean(scene);
- refine_bump_nodes();
+ simplify(scene);
if(do_bump)
bump_from_displacement(bump_in_object_space);
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index 780fdf49ca4..09932695d1f 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -17,17 +17,17 @@
#ifndef __GRAPH_H__
#define __GRAPH_H__
-#include "node.h"
-#include "node_type.h"
+#include "graph/node.h"
+#include "graph/node_type.h"
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "util_list.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_set.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_list.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_set.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -201,14 +201,14 @@ public:
/* Node definition utility macros */
#define SHADER_NODE_CLASS(type) \
- NODE_DECLARE; \
+ NODE_DECLARE \
type(); \
virtual ShaderNode *clone() const { return new type(*this); } \
virtual void compile(SVMCompiler& compiler); \
virtual void compile(OSLCompiler& compiler); \
#define SHADER_NODE_NO_CLONE_CLASS(type) \
- NODE_DECLARE; \
+ NODE_DECLARE \
type(); \
virtual void compile(SVMCompiler& compiler); \
virtual void compile(OSLCompiler& compiler); \
@@ -240,6 +240,7 @@ public:
list<ShaderNode*> nodes;
size_t num_node_ids;
bool finalized;
+ bool simplified;
ShaderGraph();
~ShaderGraph();
@@ -255,9 +256,9 @@ public:
void relink(ShaderNode *node, ShaderOutput *from, ShaderOutput *to);
void remove_proxy_nodes();
+ void simplify(Scene *scene);
void finalize(Scene *scene,
bool do_bump = false,
- bool do_osl = false,
bool do_simplify = false,
bool bump_in_object_space = false);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index fd8a1262208..a8c4f446bea 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#include "device.h"
-#include "image.h"
-#include "scene.h"
+#include "device/device.h"
+#include "render/image.h"
+#include "render/scene.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_path.h"
-#include "util_progress.h"
-#include "util_texture.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_path.h"
+#include "util/util_progress.h"
+#include "util/util_texture.h"
#ifdef WITH_OSL
#include <OSL/oslexec.h>
@@ -156,6 +156,16 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
}
}
+ /* Perform preliminary checks, with meaningful logging. */
+ if(!path_exists(filename)) {
+ VLOG(1) << "File '" << filename << "' does not exist.";
+ return IMAGE_DATA_TYPE_BYTE4;
+ }
+ if(path_is_directory(filename)) {
+ VLOG(1) << "File '" << filename << "' is a directory, can't use as image.";
+ return IMAGE_DATA_TYPE_BYTE4;
+ }
+
ImageInput *in = ImageInput::create(filename);
if(in) {
@@ -285,9 +295,8 @@ int ImageManager::add_image(const string& filename,
thread_scoped_lock device_lock(device_mutex);
- /* Do we have a float? */
- if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4)
- is_float = true;
+ /* Check whether it's a float texture. */
+ is_float = (type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4);
/* No single channel and half textures on CUDA (Fermi) and no half on OpenCL, use available slots */
if((type == IMAGE_DATA_TYPE_FLOAT ||
@@ -433,6 +442,11 @@ bool ImageManager::file_load_image_generic(Image *img, ImageInput **in, int &wid
return false;
if(!img->builtin_data) {
+ /* NOTE: Error logging is done in meta data acquisition. */
+ if(!path_exists(img->filename) || path_is_directory(img->filename)) {
+ return false;
+ }
+
/* load image from file through OIIO */
*in = ImageInput::create(img->filename);
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 494c74f0cdd..996b5a5b65f 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -17,13 +17,13 @@
#ifndef __IMAGE_H__
#define __IMAGE_H__
-#include "device.h"
-#include "device_memory.h"
+#include "device/device.h"
+#include "device/device_memory.h"
-#include "util_image.h"
-#include "util_string.h"
-#include "util_thread.h"
-#include "util_vector.h"
+#include "util/util_image.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp
index 1ab0f9874f2..a004bb5b856 100644
--- a/intern/cycles/render/integrator.cpp
+++ b/intern/cycles/render/integrator.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "device.h"
-#include "integrator.h"
-#include "film.h"
-#include "light.h"
-#include "scene.h"
-#include "shader.h"
-#include "sobol.h"
-
-#include "util_foreach.h"
-#include "util_hash.h"
+#include "device/device.h"
+#include "render/integrator.h"
+#include "render/film.h"
+#include "render/light.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/sobol.h"
+
+#include "util/util_foreach.h"
+#include "util/util_hash.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h
index 27fff4831e5..9501d7f8416 100644
--- a/intern/cycles/render/integrator.h
+++ b/intern/cycles/render/integrator.h
@@ -17,9 +17,9 @@
#ifndef __INTEGRATOR_H__
#define __INTEGRATOR_H__
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "node.h"
+#include "graph/node.h"
CCL_NAMESPACE_BEGIN
@@ -29,7 +29,7 @@ class Scene;
class Integrator : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
int min_bounce;
int max_bounce;
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index 2245c861d5a..4886dcd563f 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -14,19 +14,19 @@
* limitations under the License.
*/
-#include "background.h"
-#include "device.h"
-#include "integrator.h"
-#include "film.h"
-#include "light.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "shader.h"
-
-#include "util_foreach.h"
-#include "util_progress.h"
-#include "util_logging.h"
+#include "render/background.h"
+#include "device/device.h"
+#include "render/integrator.h"
+#include "render/film.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/shader.h"
+
+#include "util/util_foreach.h"
+#include "util/util_progress.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
@@ -57,9 +57,9 @@ static void shade_background_pixels(Device *device, DeviceScene *dscene, int res
device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
- device->mem_alloc(d_input, MEM_READ_ONLY);
+ device->mem_alloc("shade_background_pixels_input", d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_WRITE_ONLY);
+ device->mem_alloc("shade_background_pixels_output", d_output, MEM_WRITE_ONLY);
DeviceTask main_task(DeviceTask::SHADER);
main_task.shader_input = d_input.device_pointer;
@@ -486,10 +486,18 @@ static void background_cdf(int start,
float2 *cond_cdf)
{
/* Conditional CDFs (rows, U direction). */
+ /* NOTE: It is possible to have some NaN pixels on background
+ * which will ruin CDF causing wrong shading. We replace such
+ * pixels with black.
+ */
for(int i = start; i < end; i++) {
float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
float3 env_color = (*pixels)[i * res];
float ave_luminance = average(env_color);
+ /* TODO(sergey): Consider adding average_safe(). */
+ if(!isfinite(ave_luminance)) {
+ ave_luminance = 0.0f;
+ }
cond_cdf[i * cdf_count].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count].y = 0.0f;
@@ -497,6 +505,9 @@ static void background_cdf(int start,
for(int j = 1; j < res; j++) {
env_color = (*pixels)[i * res + j];
ave_luminance = average(env_color);
+ if(!isfinite(ave_luminance)) {
+ ave_luminance = 0.0f;
+ }
cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta;
cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index f56530b6490..7e9014eb823 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -17,12 +17,12 @@
#ifndef __LIGHT_H__
#define __LIGHT_H__
-#include "kernel_types.h"
+#include "kernel/kernel_types.h"
-#include "node.h"
+#include "graph/node.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index c42b32919d4..a4dc06c4345 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -14,29 +14,29 @@
* limitations under the License.
*/
-#include "bvh.h"
-#include "bvh_build.h"
-
-#include "camera.h"
-#include "curves.h"
-#include "device.h"
-#include "graph.h"
-#include "shader.h"
-#include "light.h"
-#include "mesh.h"
-#include "nodes.h"
-#include "object.h"
-#include "scene.h"
-
-#include "osl_globals.h"
-
-#include "subd_split.h"
-#include "subd_patch_table.h"
-
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_progress.h"
-#include "util_set.h"
+#include "bvh/bvh.h"
+#include "bvh/bvh_build.h"
+
+#include "render/camera.h"
+#include "render/curves.h"
+#include "device/device.h"
+#include "render/graph.h"
+#include "render/shader.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/object.h"
+#include "render/scene.h"
+
+#include "kernel/osl/osl_globals.h"
+
+#include "subd/subd_split.h"
+#include "subd/subd_patch_table.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
+#include "util/util_set.h"
CCL_NAMESPACE_BEGIN
@@ -1873,9 +1873,14 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->prim_object.reference((uint*)&pack.prim_object[0], pack.prim_object.size());
device->tex_alloc("__prim_object", dscene->prim_object);
}
+ if(pack.prim_time.size()) {
+ dscene->prim_time.reference((float2*)&pack.prim_time[0], pack.prim_time.size());
+ device->tex_alloc("__prim_time", dscene->prim_time);
+ }
dscene->data.bvh.root = pack.root_index;
dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
+ dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
}
void MeshManager::device_update_flags(Device * /*device*/,
@@ -2152,6 +2157,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
device->tex_free(dscene->prim_visibility);
device->tex_free(dscene->prim_index);
device->tex_free(dscene->prim_object);
+ device->tex_free(dscene->prim_time);
device->tex_free(dscene->tri_shader);
device->tex_free(dscene->tri_vnormal);
device->tex_free(dscene->tri_vindex);
@@ -2173,6 +2179,7 @@ void MeshManager::device_free(Device *device, DeviceScene *dscene)
dscene->prim_visibility.clear();
dscene->prim_index.clear();
dscene->prim_object.clear();
+ dscene->prim_time.clear();
dscene->tri_shader.clear();
dscene->tri_vnormal.clear();
dscene->tri_vindex.clear();
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 5f33e30eac2..043ce9d0ffc 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -17,17 +17,18 @@
#ifndef __MESH_H__
#define __MESH_H__
-#include "attribute.h"
-#include "node.h"
-#include "shader.h"
-
-#include "util_boundbox.h"
-#include "util_list.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_transform.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "graph/node.h"
+
+#include "render/attribute.h"
+#include "render/shader.h"
+
+#include "util/util_boundbox.h"
+#include "util/util_list.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_transform.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -48,7 +49,7 @@ struct PackedPatchTable;
class Mesh : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
/* Mesh Triangle */
struct Triangle {
diff --git a/intern/cycles/render/mesh_displace.cpp b/intern/cycles/render/mesh_displace.cpp
index adc5b820298..cf28bb16bb7 100644
--- a/intern/cycles/render/mesh_displace.cpp
+++ b/intern/cycles/render/mesh_displace.cpp
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#include "device.h"
+#include "device/device.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "shader.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/shader.h"
-#include "util_foreach.h"
-#include "util_progress.h"
+#include "util/util_foreach.h"
+#include "util/util_progress.h"
CCL_NAMESPACE_BEGIN
@@ -121,9 +121,9 @@ bool MeshManager::displace(Device *device, DeviceScene *dscene, Scene *scene, Me
/* needs to be up to data for attribute access */
device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
- device->mem_alloc(d_input, MEM_READ_ONLY);
+ device->mem_alloc("displace_input", d_input, MEM_READ_ONLY);
device->mem_copy_to(d_input);
- device->mem_alloc(d_output, MEM_WRITE_ONLY);
+ device->mem_alloc("displace_output", d_output, MEM_WRITE_ONLY);
DeviceTask task(DeviceTask::SHADER);
task.shader_input = d_input.device_pointer;
diff --git a/intern/cycles/render/mesh_subdivision.cpp b/intern/cycles/render/mesh_subdivision.cpp
index 57c76a9f1c8..585ed77b026 100644
--- a/intern/cycles/render/mesh_subdivision.cpp
+++ b/intern/cycles/render/mesh_subdivision.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "mesh.h"
-#include "attribute.h"
-#include "camera.h"
+#include "render/mesh.h"
+#include "render/attribute.h"
+#include "render/camera.h"
-#include "subd_split.h"
-#include "subd_patch.h"
-#include "subd_patch_table.h"
+#include "subd/subd_split.h"
+#include "subd/subd_patch.h"
+#include "subd/subd_patch_table.h"
-#include "util_foreach.h"
-#include "util_algorithm.h"
+#include "util/util_foreach.h"
+#include "util/util_algorithm.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 13b149eddfa..1070e05a03b 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -14,20 +14,21 @@
* limitations under the License.
*/
-#include "image.h"
-#include "integrator.h"
-#include "nodes.h"
-#include "scene.h"
-#include "svm.h"
-#include "svm_color_util.h"
-#include "svm_ramp_util.h"
-#include "svm_math_util.h"
-#include "osl.h"
-#include "constant_fold.h"
-
-#include "util_sky_model.h"
-#include "util_foreach.h"
-#include "util_transform.h"
+#include "render/image.h"
+#include "render/integrator.h"
+#include "render/nodes.h"
+#include "render/scene.h"
+#include "render/svm.h"
+#include "kernel/svm/svm_color_util.h"
+#include "kernel/svm/svm_ramp_util.h"
+#include "kernel/svm/svm_math_util.h"
+#include "render/osl.h"
+#include "render/constant_fold.h"
+
+#include "util/util_sky_model.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_transform.h"
CCL_NAMESPACE_BEGIN
@@ -1931,21 +1932,38 @@ GlossyBsdfNode::GlossyBsdfNode()
void GlossyBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
distribution_orig = distribution;
}
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
if(integrator->filter_glossy == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
- ShaderInput *roughness_input = input("Roughness");
if(!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glossy BSDF.";
distribution = CLOSURE_BSDF_REFLECTION_ID;
}
}
else {
- /* Rollback to original distribution when filter glossy is used. */
- distribution = distribution_orig;
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if(roughness_input->link == NULL &&
+ distribution == CLOSURE_BSDF_REFLECTION_ID)
+ {
+ VLOG(1) << "Using GGX glossy with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_ID;
+ roughness = 0.0f;
+ }
}
closure = distribution;
}
@@ -1953,7 +1971,8 @@ void GlossyBsdfNode::simplify_settings(Scene *scene)
bool GlossyBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness <= 1e-4f;
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFLECTION_ID || roughness <= 1e-4f);
}
void GlossyBsdfNode::compile(SVMCompiler& compiler)
@@ -2008,21 +2027,38 @@ GlassBsdfNode::GlassBsdfNode()
void GlassBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
distribution_orig = distribution;
}
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
if(integrator->filter_glossy == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
- ShaderInput *roughness_input = input("Roughness");
if(!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp glass BSDF.";
distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
}
}
else {
- /* Rollback to original distribution when filter glossy is used. */
- distribution = distribution_orig;
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if(roughness_input->link == NULL &&
+ distribution == CLOSURE_BSDF_SHARP_GLASS_ID)
+ {
+ VLOG(1) << "Using GGX glass with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+ roughness = 0.0f;
+ }
}
closure = distribution;
}
@@ -2030,7 +2066,8 @@ void GlassBsdfNode::simplify_settings(Scene *scene)
bool GlassBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness <= 1e-4f;
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_SHARP_GLASS_ID || roughness <= 1e-4f);
}
void GlassBsdfNode::compile(SVMCompiler& compiler)
@@ -2085,21 +2122,38 @@ RefractionBsdfNode::RefractionBsdfNode()
void RefractionBsdfNode::simplify_settings(Scene *scene)
{
if(distribution_orig == NBUILTIN_CLOSURES) {
+ roughness_orig = roughness;
distribution_orig = distribution;
}
+ else {
+ /* By default we use original values, so we don't worry about restoring
+ * defaults later one and can only do override when needed.
+ */
+ roughness = roughness_orig;
+ distribution = distribution_orig;
+ }
Integrator *integrator = scene->integrator;
+ ShaderInput *roughness_input = input("Roughness");
if(integrator->filter_glossy == 0.0f) {
/* Fallback to Sharp closure for Roughness close to 0.
* Note: Keep the epsilon in sync with kernel!
*/
- ShaderInput *roughness_input = input("Roughness");
if(!roughness_input->link && roughness <= 1e-4f) {
+ VLOG(1) << "Using sharp refraction BSDF.";
distribution = CLOSURE_BSDF_REFRACTION_ID;
}
}
else {
- /* Rollback to original distribution when filter glossy is used. */
- distribution = distribution_orig;
+ /* If filter glossy is used we replace Sharp glossy with GGX so we can
+ * benefit from closure blur to remove unwanted noise.
+ */
+ if(roughness_input->link == NULL &&
+ distribution == CLOSURE_BSDF_REFRACTION_ID)
+ {
+ VLOG(1) << "Using GGX refraction with filter glossy.";
+ distribution = CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID;
+ roughness = 0.0f;
+ }
}
closure = distribution;
}
@@ -2107,7 +2161,8 @@ void RefractionBsdfNode::simplify_settings(Scene *scene)
bool RefractionBsdfNode::has_integrator_dependency()
{
ShaderInput *roughness_input = input("Roughness");
- return !roughness_input->link && roughness <= 1e-4f;
+ return !roughness_input->link &&
+ (distribution == CLOSURE_BSDF_REFRACTION_ID || roughness <= 1e-4f);
}
void RefractionBsdfNode::compile(SVMCompiler& compiler)
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index eb0f7977dd1..a755b653a5b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -17,10 +17,10 @@
#ifndef __NODES_H__
#define __NODES_H__
-#include "graph.h"
-#include "node.h"
+#include "render/graph.h"
+#include "graph/node.h"
-#include "util_string.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
@@ -324,7 +324,7 @@ private:
class BsdfNode : public ShaderNode {
public:
explicit BsdfNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(BsdfNode);
+ SHADER_NODE_BASE_CLASS(BsdfNode)
bool has_spatial_varying() { return true; }
void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL, ShaderInput *param4 = NULL);
@@ -388,7 +388,7 @@ public:
bool has_integrator_dependency();
ClosureType get_closure_type() { return distribution; }
- float roughness;
+ float roughness, roughness_orig;
ClosureType distribution, distribution_orig;
};
@@ -400,7 +400,7 @@ public:
bool has_integrator_dependency();
ClosureType get_closure_type() { return distribution; }
- float roughness, IOR;
+ float roughness, roughness_orig, IOR;
ClosureType distribution, distribution_orig;
};
@@ -412,7 +412,7 @@ public:
bool has_integrator_dependency();
ClosureType get_closure_type() { return distribution; }
- float roughness, IOR;
+ float roughness, roughness_orig, IOR;
ClosureType distribution, distribution_orig;
};
@@ -641,7 +641,7 @@ public:
class MixClosureWeightNode : public ShaderNode {
public:
- SHADER_NODE_CLASS(MixClosureWeightNode);
+ SHADER_NODE_CLASS(MixClosureWeightNode)
float weight;
float fac;
@@ -887,7 +887,7 @@ public:
class CurvesNode : public ShaderNode {
public:
explicit CurvesNode(const NodeType *node_type);
- SHADER_NODE_BASE_CLASS(CurvesNode);
+ SHADER_NODE_BASE_CLASS(CurvesNode)
virtual int get_group() { return NODE_GROUP_LEVEL_3; }
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 8342f376836..375abfeb27a 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "device.h"
-#include "light.h"
-#include "mesh.h"
-#include "curves.h"
-#include "object.h"
-#include "particles.h"
-#include "scene.h"
-
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_map.h"
-#include "util_progress.h"
-#include "util_vector.h"
-
-#include "subd_patch_table.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/curves.h"
+#include "render/object.h"
+#include "render/particles.h"
+#include "render/scene.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_progress.h"
+#include "util/util_vector.h"
+
+#include "subd/subd_patch_table.h"
CCL_NAMESPACE_BEGIN
@@ -49,6 +49,8 @@ NODE_DEFINE(Object)
SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
+ SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
+
return type;
}
@@ -597,6 +599,12 @@ void ObjectManager::device_update_flags(Device *device,
else {
object_flag[object_index] &= ~SD_OBJECT_HAS_VOLUME;
}
+ if(object->is_shadow_catcher) {
+ object_flag[object_index] |= SD_OBJECT_SHADOW_CATCHER;
+ }
+ else {
+ object_flag[object_index] &= ~SD_OBJECT_SHADOW_CATCHER;
+ }
if(bounds_valid) {
foreach(Object *volume_object, volume_objects) {
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 7e306fab2a8..12d7b2c81cf 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -17,14 +17,14 @@
#ifndef __OBJECT_H__
#define __OBJECT_H__
-#include "node.h"
-#include "scene.h"
+#include "graph/node.h"
+#include "render/scene.h"
-#include "util_boundbox.h"
-#include "util_param.h"
-#include "util_transform.h"
-#include "util_thread.h"
-#include "util_types.h"
+#include "util/util_boundbox.h"
+#include "util/util_param.h"
+#include "util/util_transform.h"
+#include "util/util_thread.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -40,7 +40,7 @@ struct Transform;
class Object : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
Mesh *mesh;
Transform tfm;
@@ -53,6 +53,7 @@ public:
bool use_motion;
bool hide_on_missing_motion;
bool use_holdout;
+ bool is_shadow_catcher;
float3 dupli_generated;
float2 dupli_uv;
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 67b68e63cb2..6bff29d1c76 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -14,26 +14,26 @@
* limitations under the License.
*/
-#include "device.h"
+#include "device/device.h"
-#include "graph.h"
-#include "light.h"
-#include "osl.h"
-#include "scene.h"
-#include "shader.h"
-#include "nodes.h"
+#include "render/graph.h"
+#include "render/light.h"
+#include "render/osl.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/nodes.h"
#ifdef WITH_OSL
-#include "osl_globals.h"
-#include "osl_services.h"
-#include "osl_shader.h"
+#include "kernel/osl/osl_globals.h"
+#include "kernel/osl/osl_services.h"
+#include "kernel/osl/osl_shader.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_md5.h"
-#include "util_path.h"
-#include "util_progress.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_progress.h"
#endif
@@ -1096,12 +1096,10 @@ void OSLCompiler::compile(Scene *scene, OSLGlobals *og, Shader *shader)
/* finalize */
shader->graph->finalize(scene,
false,
- true,
shader->has_integrator_dependency);
if(shader->graph_bump) {
shader->graph_bump->finalize(scene,
true,
- true,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index b131b672b8c..2be1126fdd3 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -17,13 +17,13 @@
#ifndef __OSL_H__
#define __OSL_H__
-#include "util_set.h"
-#include "util_string.h"
-#include "util_thread.h"
+#include "util/util_set.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
-#include "graph.h"
-#include "nodes.h"
-#include "shader.h"
+#include "render/graph.h"
+#include "render/nodes.h"
+#include "render/shader.h"
#ifdef WITH_OSL
#include <OSL/oslcomp.h>
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index 1a35d60fb4b..a51822a08be 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#include "device.h"
-#include "particles.h"
-#include "scene.h"
-
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_map.h"
-#include "util_progress.h"
-#include "util_vector.h"
+#include "device/device.h"
+#include "render/particles.h"
+#include "render/scene.h"
+
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_map.h"
+#include "util/util_progress.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index 2509e27b44b..66d46114b3e 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -17,8 +17,8 @@
#ifndef __PARTICLES_H__
#define __PARTICLES_H__
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 68124e78cb5..4db20338744 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -16,27 +16,27 @@
#include <stdlib.h>
-#include "background.h"
-#include "bake.h"
-#include "camera.h"
-#include "curves.h"
-#include "device.h"
-#include "film.h"
-#include "integrator.h"
-#include "light.h"
-#include "mesh.h"
-#include "object.h"
-#include "osl.h"
-#include "particles.h"
-#include "scene.h"
-#include "shader.h"
-#include "svm.h"
-#include "tables.h"
-
-#include "util_foreach.h"
-#include "util_guarded_allocator.h"
-#include "util_logging.h"
-#include "util_progress.h"
+#include "render/background.h"
+#include "render/bake.h"
+#include "render/camera.h"
+#include "render/curves.h"
+#include "device/device.h"
+#include "render/film.h"
+#include "render/integrator.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/osl.h"
+#include "render/particles.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/svm.h"
+#include "render/tables.h"
+
+#include "util/util_foreach.h"
+#include "util/util_guarded_allocator.h"
+#include "util/util_logging.h"
+#include "util/util_progress.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 8768682043f..2b5267642a2 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -17,18 +17,18 @@
#ifndef __SCENE_H__
#define __SCENE_H__
-#include "image.h"
-#include "shader.h"
+#include "render/image.h"
+#include "render/shader.h"
-#include "device_memory.h"
+#include "device/device_memory.h"
-#include "util_param.h"
-#include "util_string.h"
-#include "util_system.h"
-#include "util_texture.h"
-#include "util_thread.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_param.h"
+#include "util/util_string.h"
+#include "util/util_system.h"
+#include "util/util_texture.h"
+#include "util/util_thread.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -69,6 +69,7 @@ public:
device_vector<uint> prim_visibility;
device_vector<uint> prim_index;
device_vector<uint> prim_object;
+ device_vector<float2> prim_time;
/* mesh */
device_vector<uint> tri_shader;
diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp
index 7c01934cfd8..c9b5547b407 100644
--- a/intern/cycles/render/session.cpp
+++ b/intern/cycles/render/session.cpp
@@ -17,24 +17,24 @@
#include <string.h>
#include <limits.h>
-#include "buffers.h"
-#include "camera.h"
-#include "device.h"
-#include "graph.h"
-#include "integrator.h"
-#include "mesh.h"
-#include "object.h"
-#include "scene.h"
-#include "session.h"
-#include "bake.h"
-
-#include "util_foreach.h"
-#include "util_function.h"
-#include "util_logging.h"
-#include "util_math.h"
-#include "util_opengl.h"
-#include "util_task.h"
-#include "util_time.h"
+#include "render/buffers.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/graph.h"
+#include "render/integrator.h"
+#include "render/mesh.h"
+#include "render/object.h"
+#include "render/scene.h"
+#include "render/session.h"
+#include "render/bake.h"
+
+#include "util/util_foreach.h"
+#include "util/util_function.h"
+#include "util/util_logging.h"
+#include "util/util_math.h"
+#include "util/util_opengl.h"
+#include "util/util_task.h"
+#include "util/util_time.h"
CCL_NAMESPACE_BEGIN
@@ -230,7 +230,9 @@ void Session::run_gpu()
while(1) {
scoped_timer pause_timer;
pause_cond.wait(pause_lock);
- progress.add_skip_time(pause_timer, params.background);
+ if(pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
update_status_time(pause, no_tiles);
progress.set_update();
@@ -520,7 +522,9 @@ void Session::run_cpu()
while(1) {
scoped_timer pause_timer;
pause_cond.wait(pause_lock);
- progress.add_skip_time(pause_timer, params.background);
+ if(pause) {
+ progress.add_skip_time(pause_timer, params.background);
+ }
update_status_time(pause, no_tiles);
progress.set_update();
@@ -633,6 +637,9 @@ DeviceRequestedFeatures Session::get_requested_device_features()
requested_features.use_patch_evaluation = true;
}
#endif
+ if(object->is_shadow_catcher) {
+ requested_features.use_shadow_tricks = true;
+ }
}
BakeManager *bake_manager = scene->bake_manager;
@@ -650,6 +657,8 @@ void Session::load_kernels()
if(!kernels_loaded) {
progress.set_status("Loading render kernels (may take a few minutes the first time)");
+ scoped_timer timer;
+
DeviceRequestedFeatures requested_features = get_requested_device_features();
VLOG(2) << "Requested features:\n" << requested_features;
if(!device->load_kernels(requested_features)) {
@@ -663,6 +672,9 @@ void Session::load_kernels()
return;
}
+ progress.add_skip_time(timer, false);
+ VLOG(1) << "Total time spent loading kernels: " << time_dt() - timer.get_start();
+
kernels_loaded = true;
}
}
@@ -824,7 +836,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
int progressive_sample = tile_manager.state.sample;
int num_samples = tile_manager.get_num_effective_samples();
- int tile = tile_manager.state.num_rendered_tiles;
+ int tile = progress.get_finished_tiles();
int num_tiles = tile_manager.state.num_tiles;
/* update status */
@@ -832,7 +844,7 @@ void Session::update_status_time(bool show_pause, bool show_done)
if(!params.progressive) {
const bool is_cpu = params.device.type == DEVICE_CPU;
- const bool is_last_tile = (progress.get_finished_tiles() + 1) == num_tiles;
+ const bool is_last_tile = (tile + 1) == num_tiles;
substatus = string_printf("Path Tracing Tile %d/%d", tile, num_tiles);
@@ -883,6 +895,7 @@ void Session::path_trace()
task.need_finish_queue = params.progressive_refine;
task.integrator_branched = scene->integrator->method == Integrator::BRANCHED_PATH;
task.requested_tile_size = params.tile_size;
+ task.passes_size = tile_manager.params.get_passes_size();
device->task_add(task);
}
diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h
index c7ff1446171..a7e5f78a64d 100644
--- a/intern/cycles/render/session.h
+++ b/intern/cycles/render/session.h
@@ -17,15 +17,15 @@
#ifndef __SESSION_H__
#define __SESSION_H__
-#include "buffers.h"
-#include "device.h"
-#include "shader.h"
-#include "tile.h"
-
-#include "util_progress.h"
-#include "util_stats.h"
-#include "util_thread.h"
-#include "util_vector.h"
+#include "render/buffers.h"
+#include "device/device.h"
+#include "render/shader.h"
+#include "render/tile.h"
+
+#include "util/util_progress.h"
+#include "util/util_stats.h"
+#include "util/util_thread.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 335edcbe609..12d3c6cf832 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -14,22 +14,22 @@
* limitations under the License.
*/
-#include "background.h"
-#include "camera.h"
-#include "device.h"
-#include "graph.h"
-#include "integrator.h"
-#include "light.h"
-#include "mesh.h"
-#include "nodes.h"
-#include "object.h"
-#include "osl.h"
-#include "scene.h"
-#include "shader.h"
-#include "svm.h"
-#include "tables.h"
-
-#include "util_foreach.h"
+#include "render/background.h"
+#include "render/camera.h"
+#include "device/device.h"
+#include "render/graph.h"
+#include "render/integrator.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/object.h"
+#include "render/osl.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/svm.h"
+#include "render/tables.h"
+
+#include "util/util_foreach.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h
index 7d896652196..87fef19c592 100644
--- a/intern/cycles/render/shader.h
+++ b/intern/cycles/render/shader.h
@@ -19,20 +19,20 @@
#ifdef WITH_OSL
/* So no context pollution happens from indirectly included windows.h */
-# include "util_windows.h"
+# include "util/util_windows.h"
# include <OSL/oslexec.h>
#endif
-#include "attribute.h"
-#include "kernel_types.h"
+#include "render/attribute.h"
+#include "kernel/kernel_types.h"
-#include "node.h"
+#include "graph/node.h"
-#include "util_map.h"
-#include "util_param.h"
-#include "util_string.h"
-#include "util_thread.h"
-#include "util_types.h"
+#include "util/util_map.h"
+#include "util/util_param.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -82,7 +82,7 @@ enum DisplacementMethod {
class Shader : public Node {
public:
- NODE_DECLARE;
+ NODE_DECLARE
int pass_id;
diff --git a/intern/cycles/render/sobol.cpp b/intern/cycles/render/sobol.cpp
index e3c2e802067..ce93dc8c5d5 100644
--- a/intern/cycles/render/sobol.cpp
+++ b/intern/cycles/render/sobol.cpp
@@ -46,10 +46,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "util_debug.h"
-#include "util_types.h"
+#include "util/util_debug.h"
+#include "util/util_types.h"
-#include "sobol.h"
+#include "render/sobol.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/sobol.h b/intern/cycles/render/sobol.h
index 574f148b9a2..9fbce4e14a5 100644
--- a/intern/cycles/render/sobol.h
+++ b/intern/cycles/render/sobol.h
@@ -17,7 +17,7 @@
#ifndef __SOBOL_H__
#define __SOBOL_H__
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp
index 955b892f4c3..4cb4018e2b4 100644
--- a/intern/cycles/render/svm.cpp
+++ b/intern/cycles/render/svm.cpp
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-#include "device.h"
-#include "graph.h"
-#include "light.h"
-#include "mesh.h"
-#include "nodes.h"
-#include "scene.h"
-#include "shader.h"
-#include "svm.h"
-
-#include "util_debug.h"
-#include "util_logging.h"
-#include "util_foreach.h"
-#include "util_progress.h"
-#include "util_task.h"
+#include "device/device.h"
+#include "render/graph.h"
+#include "render/light.h"
+#include "render/mesh.h"
+#include "render/nodes.h"
+#include "render/scene.h"
+#include "render/shader.h"
+#include "render/svm.h"
+
+#include "util/util_debug.h"
+#include "util/util_logging.h"
+#include "util/util_foreach.h"
+#include "util/util_progress.h"
+#include "util/util_task.h"
CCL_NAMESPACE_BEGIN
@@ -813,7 +813,6 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_finalize: NULL);
shader->graph->finalize(scene,
false,
- false,
shader->has_integrator_dependency);
}
@@ -821,7 +820,6 @@ void SVMCompiler::compile(Scene *scene,
scoped_timer timer((summary != NULL)? &summary->time_finalize_bump: NULL);
shader->graph_bump->finalize(scene,
true,
- false,
shader->has_integrator_dependency,
shader->displacement_method == DISPLACE_BOTH);
}
diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h
index a501b6bc8b1..abbd9e50610 100644
--- a/intern/cycles/render/svm.h
+++ b/intern/cycles/render/svm.h
@@ -17,13 +17,13 @@
#ifndef __SVM_H__
#define __SVM_H__
-#include "attribute.h"
-#include "graph.h"
-#include "shader.h"
+#include "render/attribute.h"
+#include "render/graph.h"
+#include "render/shader.h"
-#include "util_set.h"
-#include "util_string.h"
-#include "util_thread.h"
+#include "util/util_set.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
index dfafd99961b..bf1ef12d602 100644
--- a/intern/cycles/render/tables.cpp
+++ b/intern/cycles/render/tables.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "device.h"
-#include "scene.h"
-#include "tables.h"
+#include "device/device.h"
+#include "render/scene.h"
+#include "render/tables.h"
-#include "util_debug.h"
-#include "util_logging.h"
+#include "util/util_debug.h"
+#include "util/util_logging.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/tables.h b/intern/cycles/render/tables.h
index 1bb70b22762..bc261c2a74d 100644
--- a/intern/cycles/render/tables.h
+++ b/intern/cycles/render/tables.h
@@ -17,7 +17,7 @@
#ifndef __TABLES_H__
#define __TABLES_H__
-#include <util_list.h>
+#include "util/util_list.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/render/tile.cpp b/intern/cycles/render/tile.cpp
index a493c3fa1cd..944e746ca2d 100644
--- a/intern/cycles/render/tile.cpp
+++ b/intern/cycles/render/tile.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "tile.h"
+#include "render/tile.h"
-#include "util_algorithm.h"
-#include "util_types.h"
+#include "util/util_algorithm.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -131,7 +131,6 @@ void TileManager::reset(BufferParams& params_, int num_samples_)
state.buffer = BufferParams();
state.sample = range_start_sample - 1;
state.num_tiles = 0;
- state.num_rendered_tiles = 0;
state.num_samples = 0;
state.resolution_divider = get_divider(params.width, params.height, start_resolution);
state.tiles.clear();
@@ -343,7 +342,6 @@ bool TileManager::next_tile(Tile& tile, int device)
tile = Tile(state.tiles[logical_device].front());
state.tiles[logical_device].pop_front();
- state.num_rendered_tiles++;
return true;
}
diff --git a/intern/cycles/render/tile.h b/intern/cycles/render/tile.h
index 5d92ebac355..622b89f7670 100644
--- a/intern/cycles/render/tile.h
+++ b/intern/cycles/render/tile.h
@@ -19,8 +19,8 @@
#include <limits.h>
-#include "buffers.h"
-#include "util_list.h"
+#include "render/buffers.h"
+#include "util/util_list.h"
CCL_NAMESPACE_BEGIN
@@ -63,7 +63,6 @@ public:
int num_samples;
int resolution_divider;
int num_tiles;
- int num_rendered_tiles;
/* Total samples over all pixels: Generally num_samples*num_pixels,
* but can be higher due to the initial resolution division for previews. */
diff --git a/intern/cycles/subd/CMakeLists.txt b/intern/cycles/subd/CMakeLists.txt
index dafb807bdf3..fe0c221ab0d 100644
--- a/intern/cycles/subd/CMakeLists.txt
+++ b/intern/cycles/subd/CMakeLists.txt
@@ -1,11 +1,6 @@
set(INC
- .
- ../graph
- ../kernel
- ../kernel/svm
- ../render
- ../util
+ ..
)
set(INC_SYS
diff --git a/intern/cycles/subd/subd_dice.cpp b/intern/cycles/subd/subd_dice.cpp
index a1bd349b167..fae815901ee 100644
--- a/intern/cycles/subd/subd_dice.cpp
+++ b/intern/cycles/subd/subd_dice.cpp
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "mesh.h"
+#include "render/camera.h"
+#include "render/mesh.h"
-#include "subd_dice.h"
-#include "subd_patch.h"
+#include "subd/subd_dice.h"
+#include "subd/subd_patch.h"
-#include "util_debug.h"
+#include "util/util_debug.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/subd/subd_dice.h b/intern/cycles/subd/subd_dice.h
index 33d13a4ab3a..c0e32be18c4 100644
--- a/intern/cycles/subd/subd_dice.h
+++ b/intern/cycles/subd/subd_dice.h
@@ -22,8 +22,8 @@
* DiagSplit. For more algorithm details, see the DiagSplit paper or the
* ARB_tessellation_shader OpenGL extension, Section 2.X.2. */
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/subd/subd_patch.cpp b/intern/cycles/subd/subd_patch.cpp
index d3319c5ccf5..fa2fe2bf113 100644
--- a/intern/cycles/subd/subd_patch.cpp
+++ b/intern/cycles/subd/subd_patch.cpp
@@ -16,12 +16,12 @@
/* Parts adapted from code in the public domain in NVidia Mesh Tools. */
-#include "mesh.h"
+#include "render/mesh.h"
-#include "subd_patch.h"
+#include "subd/subd_patch.h"
-#include "util_math.h"
-#include "util_types.h"
+#include "util/util_math.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/subd/subd_patch.h b/intern/cycles/subd/subd_patch.h
index 360c1abf27b..1bb81588835 100644
--- a/intern/cycles/subd/subd_patch.h
+++ b/intern/cycles/subd/subd_patch.h
@@ -17,8 +17,8 @@
#ifndef __SUBD_PATCH_H__
#define __SUBD_PATCH_H__
-#include "util_boundbox.h"
-#include "util_types.h"
+#include "util/util_boundbox.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/subd/subd_patch_table.cpp b/intern/cycles/subd/subd_patch_table.cpp
index d437b045c07..63bf673a90b 100644
--- a/intern/cycles/subd/subd_patch_table.cpp
+++ b/intern/cycles/subd/subd_patch_table.cpp
@@ -25,10 +25,10 @@
*
*/
-#include "subd_patch_table.h"
-#include "kernel_types.h"
+#include "subd/subd_patch_table.h"
+#include "kernel/kernel_types.h"
-#include "util_math.h"
+#include "util/util_math.h"
#ifdef WITH_OPENSUBDIV
#include <opensubdiv/far/patchTable.h>
diff --git a/intern/cycles/subd/subd_patch_table.h b/intern/cycles/subd/subd_patch_table.h
index 3166a1691d8..907f2dd6c28 100644
--- a/intern/cycles/subd/subd_patch_table.h
+++ b/intern/cycles/subd/subd_patch_table.h
@@ -17,8 +17,8 @@
#ifndef __SUBD_PATCH_TABLE_H__
#define __SUBD_PATCH_TABLE_H__
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
#ifdef WITH_OPENSUBDIV
#ifdef _MSC_VER
diff --git a/intern/cycles/subd/subd_split.cpp b/intern/cycles/subd/subd_split.cpp
index 3c91ad8ab0d..9dbfc1c4e2f 100644
--- a/intern/cycles/subd/subd_split.cpp
+++ b/intern/cycles/subd/subd_split.cpp
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-#include "camera.h"
-#include "mesh.h"
+#include "render/camera.h"
+#include "render/mesh.h"
-#include "subd_dice.h"
-#include "subd_patch.h"
-#include "subd_split.h"
+#include "subd/subd_dice.h"
+#include "subd/subd_patch.h"
+#include "subd/subd_split.h"
-#include "util_debug.h"
-#include "util_math.h"
-#include "util_types.h"
+#include "util/util_debug.h"
+#include "util/util_math.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/subd/subd_split.h b/intern/cycles/subd/subd_split.h
index a2f76dd2e03..f869cc6a48e 100644
--- a/intern/cycles/subd/subd_split.h
+++ b/intern/cycles/subd/subd_split.h
@@ -22,10 +22,10 @@
* evaluation at arbitrary points is required for this to work. See the paper
* for more details. */
-#include "subd_dice.h"
+#include "subd/subd_dice.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index d8abf671bd6..a015fef8284 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -1,6 +1,6 @@
set(INC
- .
+ ..
../../glew-mx
)
@@ -52,6 +52,7 @@ set(SRC_HEADERS
util_math.h
util_math_cdf.h
util_math_fast.h
+ util_math_intersect.h
util_md5.h
util_opengl.h
util_optimization.h
diff --git a/intern/cycles/util/util_aligned_malloc.cpp b/intern/cycles/util/util_aligned_malloc.cpp
index 15d2eb3271b..cc7252dcc58 100644
--- a/intern/cycles/util/util_aligned_malloc.cpp
+++ b/intern/cycles/util/util_aligned_malloc.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "util_aligned_malloc.h"
-#include "util_guarded_allocator.h"
+#include "util/util_aligned_malloc.h"
+#include "util/util_guarded_allocator.h"
#include <cassert>
diff --git a/intern/cycles/util/util_aligned_malloc.h b/intern/cycles/util/util_aligned_malloc.h
index ecc0f28c376..cf1e86ca916 100644
--- a/intern/cycles/util/util_aligned_malloc.h
+++ b/intern/cycles/util/util_aligned_malloc.h
@@ -17,7 +17,7 @@
#ifndef __UTIL_ALIGNED_MALLOC_H__
#define __UTIL_ALIGNED_MALLOC_H__
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_atomic.h b/intern/cycles/util/util_atomic.h
index 433e41fbbb6..6c52117ef9a 100644
--- a/intern/cycles/util/util_atomic.h
+++ b/intern/cycles/util/util_atomic.h
@@ -32,6 +32,13 @@ ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value)
}
}
+#define atomic_add_and_fetch_float(p, x) atomic_add_and_fetch_fl((p), (x))
+
+#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+
+#define CCL_LOCAL_MEM_FENCE 0
+#define ccl_barrier(flags) (void)0
+
#else /* __KERNEL_GPU__ */
#ifdef __KERNEL_OPENCL__
@@ -39,7 +46,7 @@ ATOMIC_INLINE void atomic_update_max_z(size_t *maximum_value, size_t value)
/* Float atomics implementation credits:
* http://suhorukov.blogspot.in/2011/12/opencl-11-atomic-operations-on-floating.html
*/
-ccl_device_inline void atomic_add_and_fetch_float(volatile ccl_global float *source,
+ccl_device_inline float atomic_add_and_fetch_float(volatile ccl_global float *source,
const float operand)
{
union {
@@ -56,10 +63,29 @@ ccl_device_inline void atomic_add_and_fetch_float(volatile ccl_global float *sou
} while(atomic_cmpxchg((volatile ccl_global unsigned int *)source,
prev_value.int_value,
new_value.int_value) != prev_value.int_value);
+ return new_value.float_value;
}
+#define atomic_fetch_and_add_uint32(p, x) atomic_add((p), (x))
+#define atomic_fetch_and_inc_uint32(p) atomic_inc((p))
+
+#define CCL_LOCAL_MEM_FENCE CLK_LOCAL_MEM_FENCE
+#define ccl_barrier(flags) barrier(flags)
+
#endif /* __KERNEL_OPENCL__ */
+#ifdef __KERNEL_CUDA__
+
+#define atomic_add_and_fetch_float(p, x) (atomicAdd((float*)(p), (float)(x)) + (float)(x))
+
+#define atomic_fetch_and_add_uint32(p, x) atomicAdd((unsigned int*)(p), (unsigned int)(x))
+#define atomic_fetch_and_inc_uint32(p) atomic_fetch_and_add_uint32((p), 1)
+
+#define CCL_LOCAL_MEM_FENCE
+#define ccl_barrier(flags) __syncthreads()
+
+#endif /* __KERNEL_CUDA__ */
+
#endif /* __KERNEL_GPU__ */
#endif /* __UTIL_ATOMIC_H__ */
diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h
index dfe4977aef3..ed94ca20211 100644
--- a/intern/cycles/util/util_boundbox.h
+++ b/intern/cycles/util/util_boundbox.h
@@ -20,10 +20,10 @@
#include <math.h>
#include <float.h>
-#include "util_math.h"
-#include "util_string.h"
-#include "util_transform.h"
-#include "util_types.h"
+#include "util/util_math.h"
+#include "util/util_string.h"
+#include "util/util_transform.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_color.h b/intern/cycles/util/util_color.h
index d3598f84b94..4d673dc34d8 100644
--- a/intern/cycles/util/util_color.h
+++ b/intern/cycles/util/util_color.h
@@ -17,11 +17,11 @@
#ifndef __UTIL_COLOR_H__
#define __UTIL_COLOR_H__
-#include "util_math.h"
-#include "util_types.h"
+#include "util/util_math.h"
+#include "util/util_types.h"
#ifdef __KERNEL_SSE2__
-#include "util_simd.h"
+#include "util/util_simd.h"
#endif
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_debug.cpp b/intern/cycles/util/util_debug.cpp
index 80d177d2cae..9cfa57dd741 100644
--- a/intern/cycles/util/util_debug.cpp
+++ b/intern/cycles/util/util_debug.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "util_debug.h"
+#include "util/util_debug.h"
#include <stdlib.h>
-#include "util_logging.h"
-#include "util_string.h"
+#include "util/util_logging.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
@@ -29,7 +29,8 @@ DebugFlags::CPU::CPU()
sse41(true),
sse3(true),
sse2(true),
- qbvh(true)
+ qbvh(true),
+ split_kernel(false)
{
reset();
}
@@ -55,10 +56,12 @@ void DebugFlags::CPU::reset()
#undef CHECK_CPU_FLAGS
qbvh = true;
+ split_kernel = false;
}
DebugFlags::CUDA::CUDA()
- : adaptive_compile(false)
+ : adaptive_compile(false),
+ split_kernel(false)
{
reset();
}
@@ -67,12 +70,15 @@ void DebugFlags::CUDA::reset()
{
if(getenv("CYCLES_CUDA_ADAPTIVE_COMPILE") != NULL)
adaptive_compile = true;
+
+ split_kernel = false;
}
DebugFlags::OpenCL::OpenCL()
: device_type(DebugFlags::OpenCL::DEVICE_ALL),
kernel_type(DebugFlags::OpenCL::KERNEL_DEFAULT),
- debug(false)
+ debug(false),
+ single_program(false)
{
reset();
}
@@ -112,6 +118,7 @@ void DebugFlags::OpenCL::reset()
}
/* Initialize other flags from environment variables. */
debug = (getenv("CYCLES_OPENCL_DEBUG") != NULL);
+ single_program = (getenv("CYCLES_OPENCL_SINGLE_PROGRAM") != NULL);
}
DebugFlags::DebugFlags()
@@ -133,7 +140,9 @@ std::ostream& operator <<(std::ostream &os,
<< " AVX : " << string_from_bool(debug_flags.cpu.avx) << "\n"
<< " SSE4.1 : " << string_from_bool(debug_flags.cpu.sse41) << "\n"
<< " SSE3 : " << string_from_bool(debug_flags.cpu.sse3) << "\n"
- << " SSE2 : " << string_from_bool(debug_flags.cpu.sse2) << "\n";
+ << " SSE2 : " << string_from_bool(debug_flags.cpu.sse2) << "\n"
+ << " QBVH : " << string_from_bool(debug_flags.cpu.qbvh) << "\n"
+ << " Split : " << string_from_bool(debug_flags.cpu.split_kernel) << "\n";
os << "CUDA flags:\n"
<< " Adaptive Compile: " << string_from_bool(debug_flags.cuda.adaptive_compile) << "\n";
@@ -172,9 +181,10 @@ std::ostream& operator <<(std::ostream &os,
break;
}
os << "OpenCL flags:\n"
- << " Device type : " << opencl_device_type << "\n"
- << " Kernel type : " << opencl_kernel_type << "\n"
- << " Debug : " << string_from_bool(debug_flags.opencl.debug)
+ << " Device type : " << opencl_device_type << "\n"
+ << " Kernel type : " << opencl_kernel_type << "\n"
+ << " Debug : " << string_from_bool(debug_flags.opencl.debug) << "\n"
+ << " Signle program : " << string_from_bool(debug_flags.opencl.single_program)
<< "\n";
return os;
}
diff --git a/intern/cycles/util/util_debug.h b/intern/cycles/util/util_debug.h
index 73fd228b5d9..4505d584490 100644
--- a/intern/cycles/util/util_debug.h
+++ b/intern/cycles/util/util_debug.h
@@ -20,7 +20,7 @@
#include <cassert>
#include <iostream>
-#include "util_static_assert.h"
+#include "util/util_static_assert.h"
CCL_NAMESPACE_BEGIN
@@ -46,6 +46,9 @@ public:
/* Whether QBVH usage is allowed or not. */
bool qbvh;
+
+ /* Whether split kernel is used */
+ bool split_kernel;
};
/* Descriptor of CUDA feature-set to be used. */
@@ -58,6 +61,9 @@ public:
/* Whether adaptive feature based runtime compile is enabled or not.
* Requires the CUDA Toolkit and only works on Linux atm. */
bool adaptive_compile;
+
+ /* Whether split kernel is used */
+ bool split_kernel;
};
/* Descriptor of OpenCL feature-set to be used. */
@@ -106,6 +112,9 @@ public:
/* Use debug version of the kernel. */
bool debug;
+
+ /* Use single program */
+ bool single_program;
};
/* Get instance of debug flags registry. */
diff --git a/intern/cycles/util/util_guarded_allocator.cpp b/intern/cycles/util/util_guarded_allocator.cpp
index 615ac95f324..54fa6a80df5 100644
--- a/intern/cycles/util/util_guarded_allocator.cpp
+++ b/intern/cycles/util/util_guarded_allocator.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "util_guarded_allocator.h"
-#include "util_stats.h"
+#include "util/util_guarded_allocator.h"
+#include "util/util_stats.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h
index 78453d214be..5f9dcfb2481 100644
--- a/intern/cycles/util/util_guarded_allocator.h
+++ b/intern/cycles/util/util_guarded_allocator.h
@@ -20,8 +20,8 @@
#include <cstddef>
#include <memory>
-#include "util_debug.h"
-#include "util_types.h"
+#include "util/util_debug.h"
+#include "util/util_types.h"
#ifdef WITH_BLENDER_GUARDEDALLOC
# include "../../guardedalloc/MEM_guardedalloc.h"
diff --git a/intern/cycles/util/util_half.h b/intern/cycles/util/util_half.h
index 5db3384cda4..612228dd1c1 100644
--- a/intern/cycles/util/util_half.h
+++ b/intern/cycles/util/util_half.h
@@ -17,10 +17,11 @@
#ifndef __UTIL_HALF_H__
#define __UTIL_HALF_H__
-#include "util_types.h"
+#include "util/util_types.h"
+#include "util/util_math.h"
#ifdef __KERNEL_SSE2__
-#include "util_simd.h"
+#include "util/util_simd.h"
#endif
CCL_NAMESPACE_BEGIN
@@ -110,6 +111,28 @@ ccl_device_inline float4 half4_to_float4(half4 h)
return f;
}
+ccl_device_inline half float_to_half(float f)
+{
+ const uint u = __float_as_uint(f);
+ /* Sign bit, shifted to it's position. */
+ uint sign_bit = u & 0x80000000;
+ sign_bit >>= 16;
+ /* Exponent. */
+ uint exponent_bits = u & 0x7f800000;
+ /* Non-sign bits. */
+ uint value_bits = u & 0x7fffffff;
+ value_bits >>= 13; /* Align mantissa on MSB. */
+ value_bits -= 0x1c000; /* Adjust bias. */
+ /* Flush-to-zero. */
+ value_bits = (exponent_bits < 0x38800000) ? 0 : value_bits;
+ /* Clamp-to-max. */
+ value_bits = (exponent_bits > 0x47000000) ? 0x7bff : value_bits;
+ /* Denormals-as-zero. */
+ value_bits = (exponent_bits == 0 ? 0 : value_bits);
+ /* Re-insert sign bit and return. */
+ return (value_bits | sign_bit);
+}
+
#endif
#endif
diff --git a/intern/cycles/util/util_hash.h b/intern/cycles/util/util_hash.h
index 98c3a681ff2..a30b7fe288e 100644
--- a/intern/cycles/util/util_hash.h
+++ b/intern/cycles/util/util_hash.h
@@ -17,7 +17,7 @@
#ifndef __UTIL_HASH_H__
#define __UTIL_HASH_H__
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_image.h b/intern/cycles/util/util_image.h
index c8efc551d97..18876841b5b 100644
--- a/intern/cycles/util/util_image.h
+++ b/intern/cycles/util/util_image.h
@@ -21,7 +21,7 @@
#include <OpenImageIO/imageio.h>
-#include "util_vector.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
@@ -42,4 +42,4 @@ CCL_NAMESPACE_END
#endif /* __UTIL_IMAGE_H__ */
-#include "util_image_impl.h"
+#include "util/util_image_impl.h"
diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h
index 73ecfda0855..a0f9c66f979 100644
--- a/intern/cycles/util/util_image_impl.h
+++ b/intern/cycles/util/util_image_impl.h
@@ -17,9 +17,10 @@
#ifndef __UTIL_IMAGE_IMPL_H__
#define __UTIL_IMAGE_IMPL_H__
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_image.h"
+#include "util/util_algorithm.h"
+#include "util/util_debug.h"
+#include "util/util_half.h"
+#include "util/util_image.h"
CCL_NAMESPACE_BEGIN
@@ -38,6 +39,52 @@ const T *util_image_read(const vector<T>& pixels,
return &pixels[index];
}
+/* Cast input pixel from unknown storage to float. */
+template<typename T>
+inline float cast_to_float(T value);
+
+template<>
+inline float cast_to_float(float value)
+{
+ return value;
+}
+template<>
+inline float cast_to_float(uchar value)
+{
+ return (float)value / 255.0f;
+}
+template<>
+inline float cast_to_float(half value)
+{
+ return half_to_float(value);
+}
+
+/* Cast float value to output pixel type. */
+template<typename T>
+inline T cast_from_float(float value);
+
+template<>
+inline float cast_from_float(float value)
+{
+ return value;
+}
+template<>
+inline uchar cast_from_float(float value)
+{
+ if(value < 0.0f) {
+ return 0;
+ }
+ else if(value > (1.0f - 0.5f / 255.0f)) {
+ return 255;
+ }
+ return (uchar)((255.0f * value) + 0.5f);
+}
+template<>
+inline half cast_from_float(float value)
+{
+ return float_to_half(value);
+}
+
template<typename T>
void util_image_downscale_sample(const vector<T>& pixels,
const size_t width,
@@ -71,15 +118,22 @@ void util_image_downscale_sample(const vector<T>& pixels,
components,
nx, ny, nz);
for(size_t k = 0; k < components; ++k) {
- accum[k] += pixel[k];
+ accum[k] += cast_to_float(pixel[k]);
}
++count;
}
}
}
- const float inv_count = 1.0f / (float)count;
- for(size_t k = 0; k < components; ++k) {
- result[k] = T(accum[k] * inv_count);
+ if(count != 0) {
+ const float inv_count = 1.0f / (float)count;
+ for(size_t k = 0; k < components; ++k) {
+ result[k] = cast_from_float<T>(accum[k] * inv_count);
+ }
+ }
+ else {
+ for(size_t k = 0; k < components; ++k) {
+ result[k] = T(0.0f);
+ }
}
}
diff --git a/intern/cycles/util/util_logging.cpp b/intern/cycles/util/util_logging.cpp
index 03041723e15..a5a3bd34fff 100644
--- a/intern/cycles/util/util_logging.cpp
+++ b/intern/cycles/util/util_logging.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include <util_logging.h>
+#include "util/util_logging.h"
-#include "util_math.h"
+#include "util/util_math.h"
#include <stdio.h>
#ifdef _MSC_VER
@@ -69,6 +69,15 @@ void util_logging_verbosity_set(int verbosity)
}
std::ostream& operator <<(std::ostream &os,
+ const int2 &value)
+{
+ os << "(" << value.x
+ << ", " << value.y
+ << ")";
+ return os;
+}
+
+std::ostream& operator <<(std::ostream &os,
const float3 &value)
{
os << "(" << value.x
diff --git a/intern/cycles/util/util_logging.h b/intern/cycles/util/util_logging.h
index 2aa9c25b1a0..ecf9c9cfee0 100644
--- a/intern/cycles/util/util_logging.h
+++ b/intern/cycles/util/util_logging.h
@@ -45,6 +45,7 @@ public:
#define VLOG_ONCE(level, flag) if(!flag) flag = true, VLOG(level)
+struct int2;
struct float3;
void util_logging_init(const char *argv0);
@@ -52,6 +53,8 @@ void util_logging_start(void);
void util_logging_verbosity_set(int verbosity);
std::ostream& operator <<(std::ostream &os,
+ const int2 &value);
+std::ostream& operator <<(std::ostream &os,
const float3 &value);
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h
index 2b81c8c498a..e0305b978b9 100644
--- a/intern/cycles/util/util_math.h
+++ b/intern/cycles/util/util_math.h
@@ -35,7 +35,7 @@
#endif
-#include "util_types.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -43,41 +43,41 @@ CCL_NAMESPACE_BEGIN
/* Division */
#ifndef M_PI_F
-#define M_PI_F ((float)3.14159265358979323846264338327950288) /* pi */
+#define M_PI_F (3.1415926535897932f) /* pi */
#endif
#ifndef M_PI_2_F
-#define M_PI_2_F ((float)1.57079632679489661923132169163975144) /* pi/2 */
+#define M_PI_2_F (1.5707963267948966f) /* pi/2 */
#endif
#ifndef M_PI_4_F
-#define M_PI_4_F ((float)0.785398163397448309615660845819875721) /* pi/4 */
+#define M_PI_4_F (0.7853981633974830f) /* pi/4 */
#endif
#ifndef M_1_PI_F
-#define M_1_PI_F ((float)0.318309886183790671537767526745028724) /* 1/pi */
+#define M_1_PI_F (0.3183098861837067f) /* 1/pi */
#endif
#ifndef M_2_PI_F
-#define M_2_PI_F ((float)0.636619772367581343075535053490057448) /* 2/pi */
+#define M_2_PI_F (0.6366197723675813f) /* 2/pi */
#endif
/* Multiplication */
#ifndef M_2PI_F
-#define M_2PI_F ((float)6.283185307179586476925286766559005768) /* 2*pi */
+#define M_2PI_F (6.2831853071795864f) /* 2*pi */
#endif
#ifndef M_4PI_F
-#define M_4PI_F ((float)12.56637061435917295385057353311801153) /* 4*pi */
+#define M_4PI_F (12.566370614359172f) /* 4*pi */
#endif
/* Float sqrt variations */
#ifndef M_SQRT2_F
-#define M_SQRT2_F ((float)1.41421356237309504880) /* sqrt(2) */
+#define M_SQRT2_F (1.4142135623730950f) /* sqrt(2) */
#endif
#ifndef M_LN2_F
-#define M_LN2_F ((float)0.6931471805599453) /* ln(2) */
+#define M_LN2_F (0.6931471805599453f) /* ln(2) */
#endif
#ifndef M_LN10_F
-#define M_LN10_F ((float)2.3025850929940457) /* ln(10) */
+#define M_LN10_F (2.3025850929940457f) /* ln(10) */
#endif
/* Scalar */
@@ -774,6 +774,7 @@ template<size_t index_0, size_t index_1, size_t index_2, size_t index_3> __force
return _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(b), _MM_SHUFFLE(index_3, index_2, index_1, index_0)));
}
+#if defined(__KERNEL_SSE3__)
template<> __forceinline const float4 shuffle<0, 0, 2, 2>(const float4& b)
{
return _mm_moveldup_ps(b);
@@ -783,6 +784,7 @@ template<> __forceinline const float4 shuffle<1, 1, 3, 3>(const float4& b)
{
return _mm_movehdup_ps(b);
}
+#endif
template<> __forceinline const float4 shuffle<0, 1, 0, 1>(const float4& b)
{
@@ -1241,19 +1243,6 @@ ccl_device_inline float __uint_as_float(uint i)
return u.f;
}
-/* Versions of functions which are safe for fast math. */
-ccl_device_inline bool isnan_safe(float f)
-{
- unsigned int x = __float_as_uint(f);
- return (x << 1) > 0xff000000u;
-}
-
-ccl_device_inline bool isfinite_safe(float f)
-{
- /* By IEEE 754 rule, 2*Inf equals Inf */
- unsigned int x = __float_as_uint(f);
- return (f == f) && (x == 0 || (f != 2.0f*f));
-}
/* Interpolation */
@@ -1271,6 +1260,20 @@ ccl_device_inline float triangle_area(const float3& v1, const float3& v2, const
#endif
+/* Versions of functions which are safe for fast math. */
+ccl_device_inline bool isnan_safe(float f)
+{
+ unsigned int x = __float_as_uint(f);
+ return (x << 1) > 0xff000000u;
+}
+
+ccl_device_inline bool isfinite_safe(float f)
+{
+ /* By IEEE 754 rule, 2*Inf equals Inf */
+ unsigned int x = __float_as_uint(f);
+ return (f == f) && (x == 0 || (f != 2.0f*f)) && !((x << 1) > 0xff000000u);
+}
+
/* Orthonormal vectors */
ccl_device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
@@ -1329,7 +1332,7 @@ ccl_device_inline float3 safe_divide_even_color(float3 a, float3 b)
y = (b.y != 0.0f)? a.y/b.y: 0.0f;
z = (b.z != 0.0f)? a.z/b.z: 0.0f;
- /* try to get grey even if b is zero */
+ /* try to get gray even if b is zero */
if(b.x == 0.0f) {
if(b.y == 0.0f) {
x = z;
@@ -1451,181 +1454,9 @@ ccl_device_inline float beta(float x, float y)
#endif
}
-/* Ray Intersection */
-
-ccl_device bool ray_sphere_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 sphere_P, float sphere_radius,
- float3 *isect_P, float *isect_t)
-{
- float3 d = sphere_P - ray_P;
- float radiussq = sphere_radius*sphere_radius;
- float tsq = dot(d, d);
-
- if(tsq > radiussq) { /* ray origin outside sphere */
- float tp = dot(d, ray_D);
-
- if(tp < 0.0f) /* dir points away from sphere */
- return false;
-
- float dsq = tsq - tp*tp; /* pythagoras */
-
- if(dsq > radiussq) /* closest point on ray outside sphere */
- return false;
-
- float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
-
- if(t < ray_t) {
- *isect_t = t;
- *isect_P = ray_P + ray_D*t;
- return true;
- }
- }
-
- return false;
-}
-
-ccl_device bool ray_aligned_disk_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 disk_P, float disk_radius,
- float3 *isect_P, float *isect_t)
+ccl_device_inline float xor_signmask(float x, int y)
{
- /* aligned disk normal */
- float disk_t;
- float3 disk_N = normalize_len(ray_P - disk_P, &disk_t);
- float div = dot(ray_D, disk_N);
-
- if(UNLIKELY(div == 0.0f))
- return false;
-
- /* compute t to intersection point */
- float t = -disk_t/div;
- if(t < 0.0f || t > ray_t)
- return false;
-
- /* test if within radius */
- float3 P = ray_P + ray_D*t;
- if(len_squared(P - disk_P) > disk_radius*disk_radius)
- return false;
-
- *isect_P = P;
- *isect_t = t;
-
- return true;
-}
-
-ccl_device bool ray_triangle_intersect(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 v0, float3 v1, float3 v2,
- float3 *isect_P, float *isect_t)
-{
- /* Calculate intersection */
- float3 e1 = v1 - v0;
- float3 e2 = v2 - v0;
- float3 s1 = cross(ray_D, e2);
-
- const float divisor = dot(s1, e1);
- if(UNLIKELY(divisor == 0.0f))
- return false;
-
- const float invdivisor = 1.0f/divisor;
-
- /* compute first barycentric coordinate */
- const float3 d = ray_P - v0;
- const float u = dot(d, s1)*invdivisor;
- if(u < 0.0f)
- return false;
-
- /* Compute second barycentric coordinate */
- const float3 s2 = cross(d, e1);
- const float v = dot(ray_D, s2)*invdivisor;
- if(v < 0.0f)
- return false;
-
- const float b0 = 1.0f - u - v;
- if(b0 < 0.0f)
- return false;
-
- /* compute t to intersection point */
- const float t = dot(e2, s2)*invdivisor;
- if(t < 0.0f || t > ray_t)
- return false;
-
- *isect_t = t;
- *isect_P = ray_P + ray_D*t;
-
- return true;
-}
-
-ccl_device_inline bool ray_triangle_intersect_uv(
- float3 ray_P, float3 ray_D, float ray_t,
- float3 v0, float3 v1, float3 v2,
- float *isect_u, float *isect_v, float *isect_t)
-{
- /* Calculate intersection */
- float3 e1 = v1 - v0;
- float3 e2 = v2 - v0;
- float3 s1 = cross(ray_D, e2);
-
- const float divisor = dot(s1, e1);
- if(UNLIKELY(divisor == 0.0f))
- return false;
-
- const float invdivisor = 1.0f/divisor;
-
- /* compute first barycentric coordinate */
- const float3 d = ray_P - v0;
- const float u = dot(d, s1)*invdivisor;
- if(u < 0.0f)
- return false;
-
- /* Compute second barycentric coordinate */
- const float3 s2 = cross(d, e1);
- const float v = dot(ray_D, s2)*invdivisor;
- if(v < 0.0f)
- return false;
-
- const float b0 = 1.0f - u - v;
- if(b0 < 0.0f)
- return false;
-
- /* compute t to intersection point */
- const float t = dot(e2, s2)*invdivisor;
- if(t < 0.0f || t > ray_t)
- return false;
-
- *isect_u = u;
- *isect_v = v;
- *isect_t = t;
-
- return true;
-}
-
-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, float *isect_u, float *isect_v)
-{
- 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;
-
- float3 hit = ray_P + t*ray_D;
- float3 inplane = hit - quad_P;
-
- float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f;
- if(u < 0.0f || u > 1.0f)
- return false;
-
- float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f;
- if(v < 0.0f || v > 1.0f)
- return false;
-
- if(isect_P) *isect_P = hit;
- if(isect_t) *isect_t = t;
- if(isect_u) *isect_u = u;
- if(isect_v) *isect_v = v;
-
- return true;
+ return __int_as_float(__float_as_int(x) ^ y);
}
/* projections */
@@ -1690,4 +1521,3 @@ ccl_device_inline int util_max_axis(float3 vec)
CCL_NAMESPACE_END
#endif /* __UTIL_MATH_H__ */
-
diff --git a/intern/cycles/util/util_math_cdf.cpp b/intern/cycles/util/util_math_cdf.cpp
index ec78ca15d88..c14d4793ea1 100644
--- a/intern/cycles/util/util_math_cdf.cpp
+++ b/intern/cycles/util/util_math_cdf.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "util_math_cdf.h"
+#include "util/util_math_cdf.h"
-#include "util_algorithm.h"
-#include "util_math.h"
+#include "util/util_algorithm.h"
+#include "util/util_math.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_math_cdf.h b/intern/cycles/util/util_math_cdf.h
index 47dfb68ba44..79643fe26e3 100644
--- a/intern/cycles/util/util_math_cdf.h
+++ b/intern/cycles/util/util_math_cdf.h
@@ -17,9 +17,9 @@
#ifndef __UTIL_MATH_CDF_H__
#define __UTIL_MATH_CDF_H__
-#include "util_algorithm.h"
-#include "util_math.h"
-#include "util_vector.h"
+#include "util/util_algorithm.h"
+#include "util/util_math.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_math_intersect.h b/intern/cycles/util/util_math_intersect.h
new file mode 100644
index 00000000000..2b65a0dfa48
--- /dev/null
+++ b/intern/cycles/util/util_math_intersect.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2011-2017 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __UTIL_MATH_INTERSECT_H__
+#define __UTIL_MATH_INTERSECT_H__
+
+CCL_NAMESPACE_BEGIN
+
+/* Ray Intersection */
+
+ccl_device bool ray_sphere_intersect(
+ float3 ray_P, float3 ray_D, float ray_t,
+ float3 sphere_P, float sphere_radius,
+ float3 *isect_P, float *isect_t)
+{
+ const float3 d = sphere_P - ray_P;
+ const float radiussq = sphere_radius*sphere_radius;
+ const float tsq = dot(d, d);
+
+ if(tsq > radiussq) {
+ /* Ray origin outside sphere. */
+ const float tp = dot(d, ray_D);
+ if(tp < 0.0f) {
+ /* Ray points away from sphere. */
+ return false;
+ }
+ const float dsq = tsq - tp*tp; /* pythagoras */
+ if(dsq > radiussq) {
+ /* Closest point on ray outside sphere. */
+ return false;
+ }
+ const float t = tp - sqrtf(radiussq - dsq); /* pythagoras */
+ if(t < ray_t) {
+ *isect_t = t;
+ *isect_P = ray_P + ray_D*t;
+ return true;
+ }
+ }
+ return false;
+}
+
+ccl_device bool ray_aligned_disk_intersect(
+ float3 ray_P, float3 ray_D, float ray_t,
+ float3 disk_P, float disk_radius,
+ float3 *isect_P, float *isect_t)
+{
+ /* Aligned disk normal. */
+ float disk_t;
+ const float3 disk_N = normalize_len(ray_P - disk_P, &disk_t);
+ const float div = dot(ray_D, disk_N);
+ if(UNLIKELY(div == 0.0f)) {
+ return false;
+ }
+ /* Compute t to intersection point. */
+ const float t = -disk_t/div;
+ if(t < 0.0f || t > ray_t) {
+ return false;
+ }
+ /* Test if within radius. */
+ float3 P = ray_P + ray_D*t;
+ if(len_squared(P - disk_P) > disk_radius*disk_radius) {
+ return false;
+ }
+ *isect_P = P;
+ *isect_t = t;
+ return true;
+}
+
+#if defined(__KERNEL_CUDA__) && __CUDA_ARCH__ < 300
+ccl_device_inline
+#else
+ccl_device_forceinline
+#endif
+bool ray_triangle_intersect(
+ float3 ray_P, float3 ray_dir, float ray_t,
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ const ssef *ssef_verts,
+#else
+ const float3 tri_a, const float3 tri_b, const float3 tri_c,
+#endif
+ float *isect_u, float *isect_v, float *isect_t)
+{
+#if defined(__KERNEL_SSE2__) && defined(__KERNEL_SSE__)
+ typedef ssef float3;
+ const float3 tri_a(ssef_verts[0]);
+ const float3 tri_b(ssef_verts[1]);
+ const float3 tri_c(ssef_verts[2]);
+ const float3 P(ray_P);
+ const float3 dir(ray_dir);
+#else
+# define dot3(a, b) dot(a, b)
+ const float3 P = ray_P;
+ const float3 dir = ray_dir;
+#endif
+
+ /* Calculate vertices relative to ray origin. */
+ const float3 v0 = tri_c - P;
+ const float3 v1 = tri_a - P;
+ const float3 v2 = tri_b - P;
+
+ /* Calculate triangle edges. */
+ const float3 e0 = v2 - v0;
+ const float3 e1 = v0 - v1;
+ const float3 e2 = v1 - v2;
+
+ /* Perform edge tests. */
+#ifdef __KERNEL_SSE2__
+ const float3 crossU = cross(v2 + v0, e0);
+ const float3 crossV = cross(v0 + v1, e1);
+ const float3 crossW = cross(v1 + v2, e2);
+# ifndef __KERNEL_SSE__
+ const ssef crossX(crossU.x, crossV.x, crossW.x, crossW.x);
+ const ssef crossY(crossU.y, crossV.y, crossW.y, crossW.y);
+ const ssef crossZ(crossU.z, crossV.z, crossW.z, crossW.z);
+# else
+ ssef crossX(crossU);
+ ssef crossY(crossV);
+ ssef crossZ(crossW);
+ ssef zero = _mm_setzero_ps();
+ _MM_TRANSPOSE4_PS(crossX, crossY, crossZ, zero);
+# endif
+ const ssef dirX(ray_dir.x);
+ const ssef dirY(ray_dir.y);
+ const ssef dirZ(ray_dir.z);
+ /*const*/ ssef UVWW = crossX*dirX + crossY*dirY + crossZ*dirZ;
+ const float minUVW = reduce_min(UVWW);
+ const float maxUVW = reduce_max(UVWW);
+#else /* __KERNEL_SSE2__ */
+ const float U = dot(cross(v2 + v0, e0), ray_dir);
+ const float V = dot(cross(v0 + v1, e1), ray_dir);
+ const float W = dot(cross(v1 + v2, e2), ray_dir);
+ const float minUVW = min(U, min(V, W));
+ const float maxUVW = max(U, max(V, W));
+#endif /* __KERNEL_SSE2__ */
+
+ if(minUVW < 0.0f && maxUVW > 0.0f) {
+ return false;
+ }
+
+ /* Calculate geometry normal and denominator. */
+ const float3 Ng1 = cross(e1, e0);
+ //const Vec3vfM Ng1 = stable_triangle_normal(e2,e1,e0);
+ const float3 Ng = Ng1 + Ng1;
+ const float den = dot3(Ng, dir);
+ /* Avoid division by 0. */
+ if(UNLIKELY(den == 0.0f)) {
+ return false;
+ }
+
+ /* Perform depth test. */
+ const float T = dot3(v0, Ng);
+ const int sign_den = (__float_as_int(den) & 0x80000000);
+ const float sign_T = xor_signmask(T, sign_den);
+ if((sign_T < 0.0f) ||
+ (sign_T > ray_t * xor_signmask(den, sign_den)))
+ {
+ return false;
+ }
+
+ const float inv_den = 1.0f / den;
+#ifdef __KERNEL_SSE2__
+ UVWW *= inv_den;
+ _mm_store_ss(isect_u, UVWW);
+ _mm_store_ss(isect_v, shuffle<1,1,3,3>(UVWW));
+#else
+ *isect_u = U * inv_den;
+ *isect_v = V * inv_den;
+#endif
+ *isect_t = T * inv_den;
+ return true;
+
+#undef dot3
+}
+
+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,
+ float *isect_u, float *isect_v)
+{
+ /* Perform intersection test. */
+ 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;
+ }
+ const float3 hit = ray_P + t*ray_D;
+ const float3 inplane = hit - quad_P;
+ const float u = dot(inplane, quad_u) / dot(quad_u, quad_u) + 0.5f;
+ if(u < 0.0f || u > 1.0f) {
+ return false;
+ }
+ const float v = dot(inplane, quad_v) / dot(quad_v, quad_v) + 0.5f;
+ if(v < 0.0f || v > 1.0f) {
+ return false;
+ }
+ /* Store the result. */
+ /* TODO(sergey): Check whether we can avoid some checks here. */
+ if(isect_P != NULL) *isect_P = hit;
+ if(isect_t != NULL) *isect_t = t;
+ if(isect_u != NULL) *isect_u = u;
+ if(isect_v != NULL) *isect_v = v;
+ return true;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_MATH_INTERSECT_H__ */
diff --git a/intern/cycles/util/util_md5.h b/intern/cycles/util/util_md5.h
index d0af9fdb004..e4cd66c85b0 100644
--- a/intern/cycles/util/util_md5.h
+++ b/intern/cycles/util/util_md5.h
@@ -30,8 +30,8 @@
#ifndef __UTIL_MD5_H__
#define __UTIL_MD5_H__
-#include "util_string.h"
-#include "util_types.h"
+#include "util/util_string.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_optimization.h b/intern/cycles/util/util_optimization.h
index adc141a7b28..6f70a474fe7 100644
--- a/intern/cycles/util/util_optimization.h
+++ b/intern/cycles/util/util_optimization.h
@@ -111,7 +111,7 @@
/* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
* Since we can't avoid including <windows.h>, better only include that */
-#include "util_windows.h"
+#include "util/util_windows.h"
#endif
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 5df262fcbbb..cd3067f7650 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "util_debug.h"
-#include "util_md5.h"
-#include "util_path.h"
-#include "util_string.h"
+#include "util/util_debug.h"
+#include "util/util_md5.h"
+#include "util/util_path.h"
+#include "util/util_string.h"
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/strutil.h>
@@ -45,7 +45,7 @@ OIIO_NAMESPACE_USING
# include <shlwapi.h>
#endif
-#include "util_windows.h"
+#include "util/util_windows.h"
CCL_NAMESPACE_BEGIN
@@ -320,17 +320,18 @@ static char *path_specials(const string& sub)
{
static bool env_init = false;
static char *env_shader_path;
- static char *env_kernel_path;
+ static char *env_source_path;
if(!env_init) {
env_shader_path = getenv("CYCLES_SHADER_PATH");
- env_kernel_path = getenv("CYCLES_KERNEL_PATH");
+ /* NOTE: It is KERNEL in env variable for compatibility reasons. */
+ env_source_path = getenv("CYCLES_KERNEL_PATH");
env_init = true;
}
if(env_shader_path != NULL && sub == "shader") {
return env_shader_path;
}
- else if(env_shader_path != NULL && sub == "kernel") {
- return env_kernel_path;
+ else if(env_shader_path != NULL && sub == "source") {
+ return env_source_path;
}
return NULL;
}
@@ -814,7 +815,7 @@ string path_source_replace_includes(const string& source,
/* Use line directives for better error messages. */
line = line_directive(filepath, 1)
+ token.replace(0, n_end + 1, "\n" + text + "\n")
- + line_directive(path_join(path, source_filename), i);
+ + line_directive(path_join(path, source_filename), i + 1);
}
}
}
diff --git a/intern/cycles/util/util_path.h b/intern/cycles/util/util_path.h
index 70dbb5ae403..0e5e2d2c837 100644
--- a/intern/cycles/util/util_path.h
+++ b/intern/cycles/util/util_path.h
@@ -24,10 +24,10 @@
#include <stdio.h>
-#include "util_set.h"
-#include "util_string.h"
-#include "util_types.h"
-#include "util_vector.h"
+#include "util/util_set.h"
+#include "util/util_string.h"
+#include "util/util_types.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h
index 14215056840..39c1eed04e7 100644
--- a/intern/cycles/util/util_progress.h
+++ b/intern/cycles/util/util_progress.h
@@ -23,10 +23,10 @@
* update notifications from a job running in another thread. All methods
* except for the constructor/destructor are thread safe. */
-#include "util_function.h"
-#include "util_string.h"
-#include "util_time.h"
-#include "util_thread.h"
+#include "util/util_function.h"
+#include "util/util_string.h"
+#include "util/util_time.h"
+#include "util/util_thread.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_simd.cpp b/intern/cycles/util/util_simd.cpp
index de2df612578..f90439c188b 100644
--- a/intern/cycles/util/util_simd.cpp
+++ b/intern/cycles/util/util_simd.cpp
@@ -19,7 +19,7 @@
(defined(WITH_KERNEL_NATIVE) && defined(__SSE2__))
#define __KERNEL_SSE2__
-#include "util_simd.h"
+#include "util/util_simd.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_simd.h b/intern/cycles/util/util_simd.h
index 756bd15ed25..557809a5719 100644
--- a/intern/cycles/util/util_simd.h
+++ b/intern/cycles/util/util_simd.h
@@ -20,8 +20,8 @@
#include <limits>
-#include "util_debug.h"
-#include "util_types.h"
+#include "util/util_debug.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
@@ -451,11 +451,11 @@ ccl_device_inline int bitscan(int value)
CCL_NAMESPACE_END
-#include "util_math.h"
-#include "util_sseb.h"
-#include "util_ssei.h"
-#include "util_ssef.h"
-#include "util_avxf.h"
+#include "util/util_math.h"
+#include "util/util_sseb.h"
+#include "util/util_ssei.h"
+#include "util/util_ssef.h"
+#include "util/util_avxf.h"
#endif /* __UTIL_SIMD_TYPES_H__ */
diff --git a/intern/cycles/util/util_sky_model.cpp b/intern/cycles/util/util_sky_model.cpp
index 5730986cc4f..6dda8469907 100644
--- a/intern/cycles/util/util_sky_model.cpp
+++ b/intern/cycles/util/util_sky_model.cpp
@@ -97,8 +97,8 @@ All instructions on how to use this code are in the accompanying header file.
*/
-#include "util_sky_model.h"
-#include "util_sky_model_data.h"
+#include "util/util_sky_model.h"
+#include "util/util_sky_model_data.h"
#include <assert.h>
#include <stdio.h>
diff --git a/intern/cycles/util/util_ssef.h b/intern/cycles/util/util_ssef.h
index 2f5295b5463..cf99a08efae 100644
--- a/intern/cycles/util/util_ssef.h
+++ b/intern/cycles/util/util_ssef.h
@@ -514,12 +514,12 @@ ccl_device_inline float len3(const ssef& a)
/* faster version for SSSE3 */
typedef ssei shuffle_swap_t;
-ccl_device_inline const shuffle_swap_t shuffle_swap_identity(void)
+ccl_device_inline shuffle_swap_t shuffle_swap_identity(void)
{
return _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
}
-ccl_device_inline const shuffle_swap_t shuffle_swap_swap(void)
+ccl_device_inline shuffle_swap_t shuffle_swap_swap(void)
{
return _mm_set_epi8(7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
}
@@ -534,12 +534,12 @@ ccl_device_inline const ssef shuffle_swap(const ssef& a, const shuffle_swap_t& s
/* somewhat slower version for SSE2 */
typedef int shuffle_swap_t;
-ccl_device_inline const shuffle_swap_t shuffle_swap_identity(void)
+ccl_device_inline shuffle_swap_t shuffle_swap_identity(void)
{
return 0;
}
-ccl_device_inline const shuffle_swap_t shuffle_swap_swap(void)
+ccl_device_inline shuffle_swap_t shuffle_swap_swap(void)
{
return 1;
}
diff --git a/intern/cycles/util/util_stack_allocator.h b/intern/cycles/util/util_stack_allocator.h
index d7aab5b250c..2f1799a739e 100644
--- a/intern/cycles/util/util_stack_allocator.h
+++ b/intern/cycles/util/util_stack_allocator.h
@@ -20,8 +20,8 @@
#include <cstddef>
#include <memory>
-#include "util_debug.h"
-#include "util_types.h"
+#include "util/util_debug.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_static_assert.h b/intern/cycles/util/util_static_assert.h
index 033d85e8ec6..e90049254de 100644
--- a/intern/cycles/util/util_static_assert.h
+++ b/intern/cycles/util/util_static_assert.h
@@ -43,7 +43,9 @@ template <> class StaticAssertFailure<true> {};
# endif /* __COUNTER__ */
# endif /* C++11 or MSVC2015 */
#else /* __KERNEL_GPU__ */
-# define static_assert(statement, message)
+# ifndef static_assert
+# define static_assert(statement, message)
+# endif
#endif /* __KERNEL_GPU__ */
/* TODO(sergey): For until C++11 is a bare minimum for us,
diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h
index c21a8488c81..baba549753d 100644
--- a/intern/cycles/util/util_stats.h
+++ b/intern/cycles/util/util_stats.h
@@ -17,7 +17,7 @@
#ifndef __UTIL_STATS_H__
#define __UTIL_STATS_H__
-#include "util_atomic.h"
+#include "util/util_atomic.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_string.cpp b/intern/cycles/util/util_string.cpp
index 5594aa8edb6..a1008d510d1 100644
--- a/intern/cycles/util/util_string.cpp
+++ b/intern/cycles/util/util_string.cpp
@@ -17,9 +17,9 @@
#include <stdarg.h>
#include <stdio.h>
-#include "util_foreach.h"
-#include "util_string.h"
-#include "util_windows.h"
+#include "util/util_foreach.h"
+#include "util/util_string.h"
+#include "util/util_windows.h"
#ifdef _WIN32
# ifndef vsnprintf
diff --git a/intern/cycles/util/util_string.h b/intern/cycles/util/util_string.h
index 7aeed96f00b..e2c105db9c1 100644
--- a/intern/cycles/util/util_string.h
+++ b/intern/cycles/util/util_string.h
@@ -21,7 +21,7 @@
#include <string>
#include <sstream>
-#include "util_vector.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_system.cpp b/intern/cycles/util/util_system.cpp
index 87d885c44cf..a942d738b8a 100644
--- a/intern/cycles/util/util_system.cpp
+++ b/intern/cycles/util/util_system.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "util_system.h"
+#include "util/util_system.h"
-#include "util_debug.h"
-#include "util_logging.h"
-#include "util_types.h"
-#include "util_string.h"
+#include "util/util_debug.h"
+#include "util/util_logging.h"
+#include "util/util_types.h"
+#include "util/util_string.h"
#ifdef _WIN32
# if(!defined(FREE_WINDOWS))
diff --git a/intern/cycles/util/util_system.h b/intern/cycles/util/util_system.h
index ff61b260bed..db7a45b2d59 100644
--- a/intern/cycles/util/util_system.h
+++ b/intern/cycles/util/util_system.h
@@ -17,7 +17,7 @@
#ifndef __UTIL_SYSTEM_H__
#define __UTIL_SYSTEM_H__
-#include "util_string.h"
+#include "util/util_string.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp
index 0d1fed3ebbf..fb0c34e1dc4 100644
--- a/intern/cycles/util/util_task.cpp
+++ b/intern/cycles/util/util_task.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include "util_debug.h"
-#include "util_foreach.h"
-#include "util_logging.h"
-#include "util_system.h"
-#include "util_task.h"
-#include "util_time.h"
+#include "util/util_debug.h"
+#include "util/util_foreach.h"
+#include "util/util_logging.h"
+#include "util/util_system.h"
+#include "util/util_task.h"
+#include "util/util_time.h"
//#define THREADING_DEBUG_ENABLED
diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h
index 0b82f14f66f..3ebfb007e40 100644
--- a/intern/cycles/util/util_task.h
+++ b/intern/cycles/util/util_task.h
@@ -17,10 +17,10 @@
#ifndef __UTIL_TASK_H__
#define __UTIL_TASK_H__
-#include "util_list.h"
-#include "util_string.h"
-#include "util_thread.h"
-#include "util_vector.h"
+#include "util/util_list.h"
+#include "util/util_string.h"
+#include "util/util_thread.h"
+#include "util/util_vector.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_thread.cpp b/intern/cycles/util/util_thread.cpp
index 3db8b4bd197..3dcb09804b0 100644
--- a/intern/cycles/util/util_thread.cpp
+++ b/intern/cycles/util/util_thread.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "util_thread.h"
+#include "util/util_thread.h"
-#include "util_system.h"
-#include "util_windows.h"
+#include "util/util_system.h"
+#include "util/util_windows.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h
index 427c633d2ce..1b4e87ebf03 100644
--- a/intern/cycles/util/util_thread.h
+++ b/intern/cycles/util/util_thread.h
@@ -32,7 +32,7 @@
# include <libkern/OSAtomic.h>
#endif
-#include "util_function.h"
+#include "util/util_function.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_time.cpp b/intern/cycles/util/util_time.cpp
index 59c963cfafb..7c39aa294bf 100644
--- a/intern/cycles/util/util_time.cpp
+++ b/intern/cycles/util/util_time.cpp
@@ -16,8 +16,8 @@
#include <stdlib.h>
-#include "util_time.h"
-#include "util_windows.h"
+#include "util/util_time.h"
+#include "util/util_windows.h"
#ifdef _WIN32
diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp
index 2f10540c94e..b8f182ae962 100644
--- a/intern/cycles/util/util_transform.cpp
+++ b/intern/cycles/util/util_transform.cpp
@@ -46,10 +46,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "util_transform.h"
+#include "util/util_transform.h"
-#include "util_boundbox.h"
-#include "util_math.h"
+#include "util/util_boundbox.h"
+#include "util/util_math.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h
index a0695f20488..aef168ca64d 100644
--- a/intern/cycles/util/util_transform.h
+++ b/intern/cycles/util/util_transform.h
@@ -21,8 +21,8 @@
#include <string.h>
#endif
-#include "util_math.h"
-#include "util_types.h"
+#include "util/util_math.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_types.h b/intern/cycles/util/util_types.h
index a000fae4bd6..bf4a134b998 100644
--- a/intern/cycles/util/util_types.h
+++ b/intern/cycles/util/util_types.h
@@ -37,6 +37,9 @@
#define ccl_device_noinline static
#define ccl_global
#define ccl_constant
+#define ccl_local
+#define ccl_local_param
+#define ccl_private
#define ccl_restrict __restrict
#define __KERNEL_WITH_SSE_ALIGN__
@@ -82,7 +85,7 @@
/* SIMD Types */
-#include "util_optimization.h"
+#include "util/util_optimization.h"
#endif
@@ -103,10 +106,16 @@ typedef unsigned int uint;
#endif
-#ifndef __KERNEL_GPU__
-
/* Fixed Bits Types */
+#ifdef __KERNEL_OPENCL__
+
+typedef ulong uint64_t;
+
+#endif
+
+#ifndef __KERNEL_GPU__
+
#ifdef _WIN32
typedef signed char int8_t;
@@ -171,7 +180,7 @@ struct ccl_try_align(16) int3 {
};
__forceinline int3() {}
- __forceinline int3(const __m128i a) : m128(a) {}
+ __forceinline int3(const __m128i& a) : m128(a) {}
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
@@ -193,7 +202,7 @@ struct ccl_try_align(16) int4 {
};
__forceinline int4() {}
- __forceinline int4(const __m128i a) : m128(a) {}
+ __forceinline int4(const __m128i& a) : m128(a) {}
__forceinline operator const __m128i&(void) const { return m128; }
__forceinline operator __m128i&(void) { return m128; }
@@ -265,7 +274,7 @@ struct ccl_try_align(16) float4 {
};
__forceinline float4() {}
- __forceinline float4(const __m128 a) : m128(a) {}
+ __forceinline float4(const __m128& a) : m128(a) {}
__forceinline operator const __m128&(void) const { return m128; }
__forceinline operator __m128&(void) { return m128; }
@@ -397,11 +406,6 @@ ccl_device_inline float4 make_float4(float x, float y, float z, float w)
return a;
}
-ccl_device_inline int align_up(int offset, int alignment)
-{
- return (offset + alignment - 1) & ~(alignment - 1);
-}
-
ccl_device_inline int3 make_int3(int i)
{
#ifdef __KERNEL_SSE__
@@ -476,6 +480,21 @@ ccl_device_inline int4 make_int4(const float3& f)
#endif
+ccl_device_inline size_t align_up(size_t offset, size_t alignment)
+{
+ return (offset + alignment - 1) & ~(alignment - 1);
+}
+
+ccl_device_inline size_t round_up(size_t x, size_t multiple)
+{
+ return ((x + multiple - 1) / multiple) * multiple;
+}
+
+ccl_device_inline size_t round_down(size_t x, size_t multiple)
+{
+ return (x / multiple) * multiple;
+}
+
/* Interpolation types for textures
* cuda also use texture space to store other objects */
enum InterpolationType {
diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h
index 546b17570bb..4add91a3368 100644
--- a/intern/cycles/util/util_vector.h
+++ b/intern/cycles/util/util_vector.h
@@ -23,9 +23,9 @@
#include <cstring>
#include <vector>
-#include "util_aligned_malloc.h"
-#include "util_guarded_allocator.h"
-#include "util_types.h"
+#include "util/util_aligned_malloc.h"
+#include "util/util_guarded_allocator.h"
+#include "util/util_types.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/util/util_view.cpp b/intern/cycles/util/util_view.cpp
index 9796a5f896d..10d86167921 100644
--- a/intern/cycles/util/util_view.cpp
+++ b/intern/cycles/util/util_view.cpp
@@ -17,11 +17,11 @@
#include <stdio.h>
#include <stdlib.h>
-#include "util_opengl.h"
-#include "util_string.h"
-#include "util_time.h"
-#include "util_version.h"
-#include "util_view.h"
+#include "util/util_opengl.h"
+#include "util/util_string.h"
+#include "util/util_time.h"
+#include "util/util_version.h"
+#include "util/util_view.h"
#ifdef __APPLE__
#include <GLUT/glut.h>
diff --git a/intern/cycles/util/util_windows.cpp b/intern/cycles/util/util_windows.cpp
index 4de8483564b..073db2a27db 100644
--- a/intern/cycles/util/util_windows.cpp
+++ b/intern/cycles/util/util_windows.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "util_windows.h"
+#include "util/util_windows.h"
#ifdef _WIN32
diff --git a/intern/decklink/CMakeLists.txt b/intern/decklink/CMakeLists.txt
index fbef65cdba4..b7727cbc32a 100644
--- a/intern/decklink/CMakeLists.txt
+++ b/intern/decklink/CMakeLists.txt
@@ -34,14 +34,14 @@ set(SRC
DeckLinkAPI.h
)
-if (WIN32)
+if(WIN32)
list(APPEND SRC
win/DeckLinkAPI_h.h
win/DeckLinkAPI_i.c
)
endif()
-if (UNIX AND NOT APPLE)
+if(UNIX AND NOT APPLE)
list(APPEND SRC
linux/DeckLinkAPI.h
linux/DeckLinkAPIConfiguration.h
diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h
index bcfa24b06a8..d6220ebf562 100644
--- a/intern/ffmpeg/ffmpeg_compat.h
+++ b/intern/ffmpeg/ffmpeg_compat.h
@@ -350,7 +350,12 @@ int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
FFMPEG_INLINE
int64_t av_get_pts_from_frame(AVFormatContext *avctx, AVFrame * picture)
{
- int64_t pts = picture->pkt_pts;
+ int64_t pts;
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 34, 100)
+ pts = picture->pts;
+#else
+ pts = picture->pkt_pts;
+#endif
if (pts == AV_NOPTS_VALUE) {
pts = picture->pkt_dts;
diff --git a/intern/gawain/CMakeLists.txt b/intern/gawain/CMakeLists.txt
new file mode 100644
index 00000000000..99adab851c7
--- /dev/null
+++ b/intern/gawain/CMakeLists.txt
@@ -0,0 +1,34 @@
+
+set(INC gawain)
+
+set(INC_SYS ${GLEW_INCLUDE_PATH})
+
+set(SRC
+ src/attrib_binding.c
+ src/batch.c
+ src/element.c
+ src/buffer_id.cpp
+ src/immediate.c
+ src/imm_util.c
+ src/primitive.c
+ src/shader_interface.c
+ src/vertex_buffer.c
+ src/vertex_format.c
+
+ gawain/attrib_binding.h
+ gawain/batch.h
+ gawain/buffer_id.h
+ gawain/common.h
+ gawain/element.h
+ gawain/immediate.h
+ gawain/imm_util.h
+ gawain/primitive.h
+ gawain/shader_interface.h
+ gawain/vertex_buffer.h
+ gawain/vertex_format.h
+)
+
+# remove this when we switch to core profile
+add_definitions(-DWITH_GL_PROFILE_COMPAT)
+
+blender_add_lib(bf_intern_gawain "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/gpu/gawain/attrib_binding.h b/intern/gawain/gawain/attrib_binding.h
index 9e2431ca379..9e2431ca379 100644
--- a/source/blender/gpu/gawain/attrib_binding.h
+++ b/intern/gawain/gawain/attrib_binding.h
diff --git a/source/blender/gpu/gawain/batch.h b/intern/gawain/gawain/batch.h
index 660ed9eb762..189a586f964 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/intern/gawain/gawain/batch.h
@@ -21,9 +21,11 @@ typedef enum {
READY_TO_DRAW
} BatchPhase;
-typedef struct Batch{
+#define BATCH_MAX_VBO_CT 3
+
+typedef struct Batch {
// geometry
- VertexBuffer* verts;
+ VertexBuffer* verts[BATCH_MAX_VBO_CT]; // verts[0] is required, others can be NULL
ElementList* elem; // NULL if element list not needed
PrimitiveType prim_type;
@@ -43,6 +45,8 @@ void Batch_init(Batch*, PrimitiveType, VertexBuffer*, ElementList*);
void Batch_discard(Batch*); // verts & elem are not discarded
void Batch_discard_all(Batch*); // including verts & elem
+int Batch_add_VertexBuffer(Batch*, VertexBuffer*);
+
void Batch_set_program(Batch*, GLuint program);
// Entire batch draws with one shader program, but can be redrawn later with another program.
// Vertex shader's inputs must be compatible with the batch's vertex format.
@@ -50,9 +54,11 @@ void Batch_set_program(Batch*, GLuint program);
void Batch_use_program(Batch*); // call before Batch_Uniform (temp hack?)
void Batch_done_using_program(Batch*);
+void Batch_Uniform1i(Batch*, const char* name, int value);
void Batch_Uniform1b(Batch*, const char* name, bool value);
void Batch_Uniform1f(Batch*, const char* name, float value);
void Batch_Uniform2f(Batch*, const char* name, float x, float y);
+void Batch_Uniform3f(Batch*, const char* name, float x, float y, float z);
void Batch_Uniform4f(Batch*, const char* name, float x, float y, float z, float w);
void Batch_Uniform3fv(Batch*, const char* name, const float data[3]);
void Batch_Uniform4fv(Batch*, const char* name, const float data[4]);
diff --git a/source/blender/gpu/gawain/buffer_id.h b/intern/gawain/gawain/buffer_id.h
index 3f67458d060..3f67458d060 100644
--- a/source/blender/gpu/gawain/buffer_id.h
+++ b/intern/gawain/gawain/buffer_id.h
diff --git a/source/blender/gpu/gawain/common.h b/intern/gawain/gawain/common.h
index 90340b94e4d..b734da41681 100644
--- a/source/blender/gpu/gawain/common.h
+++ b/intern/gawain/gawain/common.h
@@ -11,9 +11,8 @@
#pragma once
-// #define TRUST_NO_ONE !defined(NDEBUG)
-#define TRUST_NO_ONE 1
-// strict error checking, always enabled during early development
+#define TRUST_NO_ONE !defined(NDEBUG)
+// strict error checking, enabled for debug builds during early development
#include <GL/glew.h>
#include <stdbool.h>
@@ -23,10 +22,6 @@
#include <assert.h>
#endif
-#define PER_THREAD
-// #define PER_THREAD __thread
-// MSVC uses __declspec(thread) for C code
-
#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT))
#if APPLE_LEGACY
@@ -39,20 +34,3 @@
#undef glBindVertexArray
#define glBindVertexArray glBindVertexArrayAPPLE
#endif
-
-typedef enum {
- PRIM_POINTS = GL_POINTS,
- PRIM_LINES = GL_LINES,
- PRIM_TRIANGLES = GL_TRIANGLES,
-
-#ifdef WITH_GL_PROFILE_COMPAT
- PRIM_QUADS = GL_QUADS, // legacy GL has this, modern GL & Vulkan do not
-#endif
-
- PRIM_LINE_STRIP = GL_LINE_STRIP,
- PRIM_LINE_LOOP = GL_LINE_LOOP, // GL has this, Vulkan does not
- PRIM_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
- PRIM_TRIANGLE_FAN = GL_TRIANGLE_FAN,
-
- PRIM_NONE = 0xF
-} PrimitiveType;
diff --git a/source/blender/gpu/gawain/element.h b/intern/gawain/gawain/element.h
index 4e0d5fb0649..f22d7c0ffda 100644
--- a/source/blender/gpu/gawain/element.h
+++ b/intern/gawain/gawain/element.h
@@ -11,7 +11,7 @@
#pragma once
-#include "common.h"
+#include "primitive.h"
#define TRACK_INDEX_RANGE 1
diff --git a/source/blender/gpu/gawain/imm_util.h b/intern/gawain/gawain/imm_util.h
index 730bd7c1a3c..730bd7c1a3c 100644
--- a/source/blender/gpu/gawain/imm_util.h
+++ b/intern/gawain/gawain/imm_util.h
diff --git a/source/blender/gpu/gawain/immediate.h b/intern/gawain/gawain/immediate.h
index 53f9e6c46e1..6a039542065 100644
--- a/source/blender/gpu/gawain/immediate.h
+++ b/intern/gawain/gawain/immediate.h
@@ -12,6 +12,7 @@
#pragma once
#include "vertex_format.h"
+#include "primitive.h"
#define IMM_BATCH_COMBO 1
@@ -83,9 +84,10 @@ void immUniform2f(const char* name, float x, float y);
void immUniform2fv(const char* name, const float data[2]);
void immUniform3f(const char* name, float x, float y, float z);
void immUniform3fv(const char* name, const float data[3]);
+void immUniformArray3fv(const char* name, const float *data, int count);
void immUniform4f(const char* name, float x, float y, float z, float w);
void immUniform4fv(const char* name, const float data[4]);
-void immUniformMat4(const char* name, const float data[4][4]);
+void immUniformMatrix4fv(const char* name, const float data[4][4]);
// convenience functions for setting "uniform vec4 color"
diff --git a/intern/gawain/gawain/primitive.h b/intern/gawain/gawain/primitive.h
new file mode 100644
index 00000000000..55333be6c9e
--- /dev/null
+++ b/intern/gawain/gawain/primitive.h
@@ -0,0 +1,44 @@
+
+// Gawain geometric primitives
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+typedef enum {
+ PRIM_POINTS = GL_POINTS,
+ PRIM_LINES = GL_LINES,
+ PRIM_TRIANGLES = GL_TRIANGLES,
+
+#ifdef WITH_GL_PROFILE_COMPAT
+ PRIM_QUADS = GL_QUADS, // legacy GL has this, modern GL & Vulkan do not
+#endif
+
+ PRIM_LINE_STRIP = GL_LINE_STRIP,
+ PRIM_LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY,
+ PRIM_LINE_LOOP = GL_LINE_LOOP, // GL has this, Vulkan does not
+ PRIM_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
+ PRIM_TRIANGLE_FAN = GL_TRIANGLE_FAN,
+
+ PRIM_NONE = 0xF
+} PrimitiveType;
+
+// what types of primitives does each shader expect?
+typedef enum {
+ PRIM_CLASS_NONE = 0,
+ PRIM_CLASS_POINT = (1 << 0),
+ PRIM_CLASS_LINE = (1 << 1),
+ PRIM_CLASS_SURFACE = (1 << 2),
+ PRIM_CLASS_ANY = PRIM_CLASS_POINT | PRIM_CLASS_LINE | PRIM_CLASS_SURFACE
+} PrimitiveClass;
+
+PrimitiveClass prim_class_of_type(PrimitiveType);
+bool prim_type_belongs_to_class(PrimitiveType, PrimitiveClass);
diff --git a/intern/gawain/gawain/shader_interface.h b/intern/gawain/gawain/shader_interface.h
new file mode 100644
index 00000000000..bdb0bbf4a8c
--- /dev/null
+++ b/intern/gawain/gawain/shader_interface.h
@@ -0,0 +1,49 @@
+
+// Gawain shader interface (C --> GLSL)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include "common.h"
+
+typedef enum {
+ UNIFORM_NONE, // uninitialized/unknown
+
+ UNIFORM_MODELVIEW_3D, // mat4 ModelViewMatrix
+ UNIFORM_PROJECTION_3D, // mat4 ProjectionMatrix
+ UNIFORM_MVP_3D, // mat4 ModelViewProjectionMatrix
+ UNIFORM_NORMAL_3D, // mat3 NormalMatrix
+ UNIFORM_INV_NORMAL_3D, // mat3 InverseNormalMatrix
+
+ UNIFORM_MODELVIEW_2D, // mat3 ModelViewMatrix
+ UNIFORM_PROJECTION_2D, // mat3 ProjectionMatrix
+ UNIFORM_MVP_2D, // mat3 ModelViewProjectionMatrix
+
+ UNIFORM_COLOR, // vec4 color
+
+ UNIFORM_CUSTOM // custom uniform, not one of the above built-ins
+} BuiltinUniform;
+
+typedef struct {
+ const char* name;
+ GLenum gl_type;
+ BuiltinUniform builtin_type; // only for uniform inputs
+ GLint size;
+ GLint location;
+} ShaderInput;
+
+typedef struct {
+ uint16_t uniform_ct;
+ uint16_t attrib_ct;
+ ShaderInput inputs[0]; // dynamic size, uniforms followed by attribs
+} ShaderInterface;
+
+ShaderInterface* ShaderInterface_create(GLint program_id);
+void ShaderInterface_discard(ShaderInterface*);
diff --git a/source/blender/gpu/gawain/vertex_buffer.h b/intern/gawain/gawain/vertex_buffer.h
index 6a72cfe6ff3..6a72cfe6ff3 100644
--- a/source/blender/gpu/gawain/vertex_buffer.h
+++ b/intern/gawain/gawain/vertex_buffer.h
diff --git a/source/blender/gpu/gawain/vertex_format.h b/intern/gawain/gawain/vertex_format.h
index 66477b0cfc7..4ed9e58f376 100644
--- a/source/blender/gpu/gawain/vertex_format.h
+++ b/intern/gawain/gawain/vertex_format.h
@@ -74,7 +74,7 @@ typedef struct {
int x : 10;
int y : 10;
int z : 10;
- int w : 2; // ignored for our purposes
+ int w : 2; // 0 by default, can manually set to { -2, -1, 0, 1 }
} PackedNormal;
PackedNormal convert_i10_v3(const float data[3]);
diff --git a/source/blender/gpu/gawain/attrib_binding.c b/intern/gawain/src/attrib_binding.c
index bb42aaf66eb..bb42aaf66eb 100644
--- a/source/blender/gpu/gawain/attrib_binding.c
+++ b/intern/gawain/src/attrib_binding.c
diff --git a/source/blender/gpu/gawain/batch.c b/intern/gawain/src/batch.c
index 55ccd94a555..cac34d445bb 100644
--- a/source/blender/gpu/gawain/batch.c
+++ b/intern/gawain/src/batch.c
@@ -30,11 +30,13 @@ void Batch_init(Batch* batch, PrimitiveType prim_type, VertexBuffer* verts, Elem
{
#if TRUST_NO_ONE
assert(verts != NULL);
- assert(prim_type == PRIM_POINTS || prim_type == PRIM_LINES || prim_type == PRIM_TRIANGLES);
+ // assert(prim_type == PRIM_POINTS || prim_type == PRIM_LINES || prim_type == PRIM_TRIANGLES);
// we will allow other primitive types in a future update
#endif
- batch->verts = verts;
+ batch->verts[0] = verts;
+ for (int v = 1; v < BATCH_MAX_VBO_CT; ++v)
+ batch->verts[v] = NULL;
batch->elem = elem;
batch->prim_type = prim_type;
batch->phase = READY_TO_DRAW;
@@ -50,12 +52,43 @@ void Batch_discard(Batch* batch)
void Batch_discard_all(Batch* batch)
{
- VertexBuffer_discard(batch->verts);
+ for (int v = 0; v < BATCH_MAX_VBO_CT; ++v)
+ {
+ if (batch->verts[v] == NULL)
+ break;
+ VertexBuffer_discard(batch->verts[v]);
+ }
+
if (batch->elem)
ElementList_discard(batch->elem);
+
Batch_discard(batch);
}
+int Batch_add_VertexBuffer(Batch* batch, VertexBuffer* verts)
+ {
+ for (unsigned v = 0; v < BATCH_MAX_VBO_CT; ++v)
+ {
+ if (batch->verts[v] == NULL)
+ {
+#if TRUST_NO_ONE
+ // for now all VertexBuffers must have same vertex_ct
+ assert(verts->vertex_ct == batch->verts[0]->vertex_ct);
+ // in the near future we will enable instanced attribs which have their own vertex_ct
+#endif
+ batch->verts[v] = verts;
+ // TODO: mark dirty so we can keep attrib bindings up-to-date
+ return v;
+ }
+ }
+
+ // we only make it this far if there is no room for another VertexBuffer
+#if TRUST_NO_ONE
+ assert(false);
+#endif
+ return -1;
+ }
+
void Batch_set_program(Batch* batch, GLuint program)
{
#if TRUST_NO_ONE
@@ -70,43 +103,48 @@ void Batch_set_program(Batch* batch, GLuint program)
static void Batch_update_program_bindings(Batch* batch)
{
- const VertexFormat* format = &batch->verts->format;
-
- const unsigned attrib_ct = format->attrib_ct;
- const unsigned stride = format->stride;
-
// disable all as a precaution
// why are we not using prev_attrib_enabled_bits?? see immediate.c
for (unsigned a_idx = 0; a_idx < MAX_VERTEX_ATTRIBS; ++a_idx)
glDisableVertexAttribArray(a_idx);
- VertexBuffer_use(batch->verts);
-
- for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx)
+ for (int v = 0; v < BATCH_MAX_VBO_CT; ++v)
{
- const Attrib* a = format->attribs + a_idx;
+ VertexBuffer* verts = batch->verts[v];
+ if (verts == NULL)
+ break;
- const GLvoid* pointer = (const GLubyte*)0 + a->offset;
+ const VertexFormat* format = &verts->format;
- const GLint loc = glGetAttribLocation(batch->program, a->name);
+ const unsigned attrib_ct = format->attrib_ct;
+ const unsigned stride = format->stride;
-#if TRUST_NO_ONE
- assert(loc != -1);
-#endif
-
- glEnableVertexAttribArray(loc);
+ VertexBuffer_use(verts);
- switch (a->fetch_mode)
+ for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx)
{
- case KEEP_FLOAT:
- case CONVERT_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
- break;
- case NORMALIZE_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
- break;
- case KEEP_INT:
- glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
+ const Attrib* a = format->attribs + a_idx;
+
+ const GLvoid* pointer = (const GLubyte*)0 + a->offset;
+
+ const GLint loc = glGetAttribLocation(batch->program, a->name);
+
+ if (loc == -1) continue;
+
+ glEnableVertexAttribArray(loc);
+
+ switch (a->fetch_mode)
+ {
+ case KEEP_FLOAT:
+ case CONVERT_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
+ break;
+ case NORMALIZE_INT_TO_FLOAT:
+ glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
+ break;
+ case KEEP_INT:
+ glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
+ }
}
}
@@ -135,6 +173,17 @@ void Batch_done_using_program(Batch* batch)
}
}
+void Batch_Uniform1i(Batch* batch, const char* name, int value)
+ {
+ int loc = glGetUniformLocation(batch->program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform1i(loc, value);
+ }
+
void Batch_Uniform1b(Batch* batch, const char* name, bool value)
{
int loc = glGetUniformLocation(batch->program, name);
@@ -157,6 +206,17 @@ void Batch_Uniform2f(Batch* batch, const char* name, float x, float y)
glUniform2f(loc, x, y);
}
+void Batch_Uniform3f(Batch* batch, const char* name, float x, float y, float z)
+ {
+ int loc = glGetUniformLocation(batch->program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+#endif
+
+ glUniform3f(loc, x, y, z);
+ }
+
void Batch_Uniform4f(Batch* batch, const char* name, float x, float y, float z, float w)
{
int loc = glGetUniformLocation(batch->program, name);
@@ -206,7 +266,12 @@ static void Batch_prime(Batch* batch)
batch->vao_id = vao_id_alloc();
glBindVertexArray(batch->vao_id);
- VertexBuffer_use(batch->verts);
+ for (int v = 0; v < BATCH_MAX_VBO_CT; ++v)
+ {
+ if (batch->verts[v] == NULL)
+ break;
+ VertexBuffer_use(batch->verts[v]);
+ }
if (batch->elem)
ElementList_use(batch->elem);
@@ -247,7 +312,7 @@ void Batch_draw(Batch* batch)
#endif
}
else
- glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct);
+ glDrawArrays(batch->prim_type, 0, batch->verts[0]->vertex_ct);
Batch_done_using_program(batch);
glBindVertexArray(0);
@@ -284,7 +349,7 @@ void Batch_draw_stupid(Batch* batch)
#endif
}
else
- glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct);
+ glDrawArrays(batch->prim_type, 0, batch->verts[0]->vertex_ct);
// Batch_done_using_program(batch);
glBindVertexArray(0);
@@ -332,7 +397,7 @@ void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int in
glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
}
else
- glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count);
+ glDrawArraysInstanced(batch->prim_type, 0, batch->verts[0]->vertex_ct, instance_count);
// Batch_done_using_program(batch);
glBindVertexArray(0);
diff --git a/source/blender/gpu/gawain/buffer_id.cpp b/intern/gawain/src/buffer_id.cpp
index 450656c4ebf..450656c4ebf 100644
--- a/source/blender/gpu/gawain/buffer_id.cpp
+++ b/intern/gawain/src/buffer_id.cpp
diff --git a/source/blender/gpu/gawain/element.c b/intern/gawain/src/element.c
index 3c3ca1c7626..3c3ca1c7626 100644
--- a/source/blender/gpu/gawain/element.c
+++ b/intern/gawain/src/element.c
diff --git a/source/blender/gpu/gawain/imm_util.c b/intern/gawain/src/imm_util.c
index 74caeb6fd3a..74caeb6fd3a 100644
--- a/source/blender/gpu/gawain/imm_util.c
+++ b/intern/gawain/src/imm_util.c
diff --git a/source/blender/gpu/gawain/immediate.c b/intern/gawain/src/immediate.c
index b7aad530620..4e584dcb3cb 100644
--- a/source/blender/gpu/gawain/immediate.c
+++ b/intern/gawain/src/immediate.c
@@ -51,8 +51,8 @@ typedef struct {
// size of internal buffer -- make this adjustable?
#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
-static PER_THREAD bool initialized = false;
-static PER_THREAD Immediate imm;
+static bool initialized = false;
+static Immediate imm;
void immInit(void)
{
@@ -144,6 +144,7 @@ void immUnbindProgram(void)
imm.bound_program = 0;
}
+#if TRUST_NO_ONE
static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, PrimitiveType prim_type)
{
// does vertex_ct make sense for this primitive type?
@@ -159,6 +160,8 @@ static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, Primitive
case PRIM_LINE_STRIP:
case PRIM_LINE_LOOP:
return vertex_ct >= 2;
+ case PRIM_LINE_STRIP_ADJACENCY:
+ return vertex_ct >= 4;
case PRIM_TRIANGLES:
return vertex_ct % 3 == 0;
case PRIM_TRIANGLE_STRIP:
@@ -172,6 +175,7 @@ static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, Primitive
return false;
}
}
+#endif
void immBegin(PrimitiveType prim_type, unsigned vertex_ct)
{
@@ -385,7 +389,7 @@ void immEnd(void)
{
if (buffer_bytes_used != imm.buffer_bytes_mapped)
{
- VertexBuffer_resize_data(imm.batch->verts, imm.vertex_ct);
+ VertexBuffer_resize_data(imm.batch->verts[0], imm.vertex_ct);
// TODO: resize only if vertex count is much smaller
}
@@ -771,6 +775,18 @@ void immUniform3fv(const char* name, const float data[3])
glUniform3fv(loc, 1, data);
}
+void immUniformArray3fv(const char* name, const float *data, int count)
+ {
+ int loc = glGetUniformLocation(imm.bound_program, name);
+
+#if TRUST_NO_ONE
+ assert(loc != -1);
+ assert(count > 0);
+#endif
+
+ glUniform3fv(loc, count, data);
+ }
+
void immUniform4f(const char* name, float x, float y, float z, float w)
{
int loc = glGetUniformLocation(imm.bound_program, name);
@@ -793,7 +809,7 @@ void immUniform4fv(const char* name, const float data[4])
glUniform4fv(loc, 1, data);
}
-void immUniformMat4(const char* name, const float data[4][4])
+void immUniformMatrix4fv(const char* name, const float data[4][4])
{
int loc = glGetUniformLocation(imm.bound_program, name);
diff --git a/intern/gawain/src/primitive.c b/intern/gawain/src/primitive.c
new file mode 100644
index 00000000000..95472c289e8
--- /dev/null
+++ b/intern/gawain/src/primitive.c
@@ -0,0 +1,41 @@
+
+// Gawain geometric primitives
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "primitive.h"
+
+PrimitiveClass prim_class_of_type(PrimitiveType prim_type)
+ {
+ static const PrimitiveClass classes[] =
+ {
+ [PRIM_NONE] = PRIM_CLASS_NONE,
+ [PRIM_POINTS] = PRIM_CLASS_POINT,
+ [PRIM_LINES] = PRIM_CLASS_LINE,
+ [PRIM_LINE_STRIP] = PRIM_CLASS_LINE,
+ [PRIM_LINE_LOOP] = PRIM_CLASS_LINE,
+ [PRIM_TRIANGLES] = PRIM_CLASS_SURFACE,
+ [PRIM_TRIANGLE_STRIP] = PRIM_CLASS_SURFACE,
+ [PRIM_TRIANGLE_FAN] = PRIM_CLASS_SURFACE,
+
+#ifdef WITH_GL_PROFILE_COMPAT
+ [PRIM_QUADS] = PRIM_CLASS_SURFACE,
+#endif
+ };
+
+ return classes[prim_type];
+ }
+
+bool prim_type_belongs_to_class(PrimitiveType prim_type, PrimitiveClass prim_class)
+ {
+ if (prim_class == PRIM_CLASS_NONE && prim_type == PRIM_NONE)
+ return true;
+
+ return prim_class & prim_class_of_type(prim_type);
+ }
diff --git a/intern/gawain/src/shader_interface.c b/intern/gawain/src/shader_interface.c
new file mode 100644
index 00000000000..93a1283d895
--- /dev/null
+++ b/intern/gawain/src/shader_interface.c
@@ -0,0 +1,140 @@
+
+// Gawain shader interface (C --> GLSL)
+//
+// This code is part of the Gawain library, with modifications
+// specific to integration with Blender.
+//
+// Copyright 2017 Mike Erwin
+//
+// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
+// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+#include "shader_interface.h"
+#include <stdlib.h>
+#include <stddef.h>
+
+#define DEBUG_SHADER_INTERFACE 0
+
+#if DEBUG_SHADER_INTERFACE
+ #include <stdio.h>
+#endif
+
+#if 0
+
+static const char* BuiltinUniform_name(BuiltinUniform u)
+ {
+ static const char* names[] =
+ {
+ [UNIFORM_NONE] = NULL,
+
+ [UNIFORM_MODELVIEW_3D] = "ModelViewMatrix",
+ [UNIFORM_PROJECTION_3D] = "ProjectionMatrix",
+ [UNIFORM_MVP_3D] = "ModelViewProjectionMatrix",
+ [UNIFORM_NORMAL_3D] = "NormalMatrix",
+ [UNIFORM_INV_NORMAL_3D] = "InverseNormalMatrix",
+
+ [UNIFORM_MODELVIEW_2D] = "ModelViewMatrix",
+ [UNIFORM_PROJECTION_2D] = "ProjectionMatrix",
+ [UNIFORM_MVP_2D] = "ModelViewProjectionMatrix",
+
+ [UNIFORM_COLOR] = "color",
+
+ [UNIFORM_CUSTOM] = NULL
+ };
+
+ return names[u];
+ }
+
+#endif
+
+static bool setup_builtin_uniform(ShaderInput* input, const char* name)
+ {
+ // TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types
+
+ // TODO: detect built-in uniforms (gl_type and name must match)
+ // if a match is found, use BuiltinUniform_name so name buffer space can be reclaimed
+ input->name = name;
+ input->builtin_type = UNIFORM_CUSTOM;
+ return false;
+ }
+
+ShaderInterface* ShaderInterface_create(GLint program)
+ {
+#if DEBUG_SHADER_INTERFACE
+ printf("%s {\n", __func__); // enter function
+#endif
+
+ GLint uniform_ct, attrib_ct;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_ct);
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attrib_ct);
+ const GLint input_ct = uniform_ct + attrib_ct;
+
+ GLint max_uniform_name_len, max_attrib_name_len;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+ glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attrib_name_len);
+ const uint32_t name_buffer_len = uniform_ct * max_uniform_name_len + attrib_ct * max_attrib_name_len;
+
+ // allocate enough space for input counts, details for each input, and a buffer for name strings
+ ShaderInterface* shaderface = calloc(1, offsetof(ShaderInterface, inputs) + input_ct * sizeof(ShaderInput) + name_buffer_len);
+
+ char* name_buffer = (char*)shaderface + offsetof(ShaderInterface, inputs) + input_ct * sizeof(ShaderInput);
+ uint32_t name_buffer_offset = 0;
+
+ for (uint32_t i = 0; i < uniform_ct; ++i)
+ {
+ ShaderInput* input = shaderface->inputs + i;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ char* name = name_buffer + name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveUniform(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+
+ if (setup_builtin_uniform(input, name))
+ ; // reclaim space from name buffer (don't advance offset)
+ else
+ name_buffer_offset += name_len + 1; // include NULL terminator
+
+ input->location = glGetUniformLocation(program, name);
+
+#if DEBUG_SHADER_INTERFACE
+ printf("uniform[%u] '%s' at location %d\n", i, name, input->location);
+#endif
+ }
+
+ for (uint32_t i = 0; i < attrib_ct; ++i)
+ {
+ ShaderInput* input = shaderface->inputs + uniform_ct + i;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ char* name = name_buffer + name_buffer_offset;
+ GLsizei name_len = 0;
+
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
+
+ // TODO: reject DOUBLE gl_types
+
+ input->name = name;
+ name_buffer_offset += name_len + 1; // include NULL terminator
+
+ input->location = glGetAttribLocation(program, name);
+
+#if DEBUG_SHADER_INTERFACE
+ printf("attrib[%u] '%s' at location %d\n", i, name, input->location);
+#endif
+ }
+
+ // TODO: realloc shaderface to shrink name buffer
+ // each input->name will need adjustment (except static built-in names)
+
+#if DEBUG_SHADER_INTERFACE
+ printf("using %u of %u bytes from name buffer\n", name_buffer_offset, name_buffer_len);
+ printf("}\n"); // exit function
+#endif
+
+ return shaderface;
+ }
+
+void ShaderInterface_discard(ShaderInterface* shaderface)
+ {
+ // allocated as one chunk, so discard is simple
+ free(shaderface);
+ }
diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/intern/gawain/src/vertex_buffer.c
index 827703403e3..827703403e3 100644
--- a/source/blender/gpu/gawain/vertex_buffer.c
+++ b/intern/gawain/src/vertex_buffer.c
diff --git a/source/blender/gpu/gawain/vertex_format.c b/intern/gawain/src/vertex_format.c
index 671b979a810..d42398f3a4f 100644
--- a/source/blender/gpu/gawain/vertex_format.c
+++ b/intern/gawain/src/vertex_format.c
@@ -120,8 +120,10 @@ unsigned add_attrib(VertexFormat* format, const char* name, VertexCompType comp_
break;
#if USE_10_10_10
case COMP_I10:
- assert(comp_ct == 3); // 10_10_10 format intended for normals (xyz) or colors (rgb)
- assert(fetch_mode == NORMALIZE_INT_TO_FLOAT);
+ // 10_10_10 format intended for normals (xyz) or colors (rgb)
+ // extra component packed.w can be manually set to { -2, -1, 0, 1 }
+ assert(comp_ct == 3 || comp_ct == 4);
+ assert(fetch_mode == NORMALIZE_INT_TO_FLOAT); // not strictly required, may relax later
break;
#endif
default:
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index ff1922af4f3..6887063eae9 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -908,6 +908,11 @@ extern int GHOST_UseNativePixels(void);
extern float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle);
/**
+ * Returns the suggested DPI for this window.
+ */
+extern GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle);
+
+/**
* Enable IME attached to the given window, i.e. allows user-input
* events to be dispatched to the IME.
* \param windowhandle Window handle of the caller
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index 688ebecf557..4a4d6be5ced 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -332,6 +332,12 @@ public:
virtual float getNativePixelSize(void) = 0;
+ /**
+ * Returns the recommended DPI for this window.
+ * \return The recommended DPI for this window.
+ */
+ virtual GHOST_TUns16 getDPIHint() = 0;
+
#ifdef WITH_INPUT_IME
/**
* Enable IME attached to the given window, i.e. allows user-input
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 9ee4599a4a6..02b5063e515 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -189,6 +189,7 @@ typedef enum {
GHOST_kEventWindowUpdate,
GHOST_kEventWindowSize,
GHOST_kEventWindowMove,
+ GHOST_kEventWindowDPIHintChanged,
GHOST_kEventDraggingEntered,
GHOST_kEventDraggingUpdated,
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index 41bc735e1e2..ce653188760 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -914,6 +914,12 @@ float GHOST_GetNativePixelSize(GHOST_WindowHandle windowhandle)
return 1.0f;
}
+GHOST_TUns16 GHOST_GetDPIHint(GHOST_WindowHandle windowhandle)
+{
+ GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
+ return window->getDPIHint();
+}
+
#ifdef WITH_INPUT_IME
void GHOST_BeginIME(GHOST_WindowHandle windowhandle,
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 7d55a973f91..240d7ccd2fe 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -111,6 +111,11 @@
#define VK_MEDIA_PLAY_PAUSE 0xB3
#endif // VK_MEDIA_PLAY_PAUSE
+// Window message newer than Windows 7
+#ifndef WM_DPICHANGED
+#define WM_DPICHANGED 0x02E0
+#endif // WM_DPICHANGED
+
/* Workaround for some laptop touchpads, some of which seems to
* have driver issues which makes it so window function receives
* the message, but PeekMessage doesn't pick those messages for
@@ -152,6 +157,27 @@ static void initRawInput()
#undef DEVICE_COUNT
}
+#ifndef DPI_ENUMS_DECLARED
+typedef enum PROCESS_DPI_AWARENESS {
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+
+typedef enum MONITOR_DPI_TYPE {
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+
+#define USER_DEFAULT_SCREEN_DPI 96
+
+#define DPI_ENUMS_DECLARED
+#endif
+typedef HRESULT(API * GHOST_WIN32_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
+typedef BOOL(API * GHOST_WIN32_EnableNonClientDpiScaling)(HWND);
+
GHOST_SystemWin32::GHOST_SystemWin32()
: m_hasPerformanceCounter(false), m_freq(0), m_start(0)
{
@@ -161,6 +187,18 @@ GHOST_SystemWin32::GHOST_SystemWin32()
m_consoleStatus = 1;
+ // Tell Windows we are per monitor DPI aware. This disables the default
+ // blurry scaling and enables WM_DPICHANGED to allow us to draw at proper DPI.
+ HMODULE m_shcore = ::LoadLibrary("Shcore.dll");
+ if (m_shcore) {
+ GHOST_WIN32_SetProcessDpiAwareness fpSetProcessDpiAwareness =
+ (GHOST_WIN32_SetProcessDpiAwareness) ::GetProcAddress(m_shcore, "SetProcessDpiAwareness");
+
+ if (fpSetProcessDpiAwareness) {
+ fpSetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+ }
+ }
+
// Check if current keyboard layout uses AltGr and save keylayout ID for
// specialized handling if keys like VK_OEM_*. I.e. french keylayout
// generates VK_OEM_8 for their exclamation key (key left of right shift)
@@ -922,6 +960,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized");
if (hwnd) {
+ if(msg == WM_NCCREATE) {
+ // Tell Windows to automatically handle scaling of non-client areas
+ // such as the caption bar. EnableNonClientDpiScaling was introduced in Windows 10
+ HMODULE m_user32 = ::LoadLibrary("User32.dll");
+ if (m_user32) {
+ GHOST_WIN32_EnableNonClientDpiScaling fpEnableNonClientDpiScaling =
+ (GHOST_WIN32_EnableNonClientDpiScaling) ::GetProcAddress(m_user32, "EnableNonClientDpiScaling");
+
+ if (fpEnableNonClientDpiScaling) {
+ fpEnableNonClientDpiScaling(hwnd);
+ }
+ }
+ }
+
GHOST_WindowWin32 *window = (GHOST_WindowWin32 *)::GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (window) {
switch (msg) {
@@ -1294,6 +1346,32 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
break;
+ case WM_DPICHANGED:
+ /* The WM_DPICHANGED message is sent when the effective dots per inch (dpi) for a window has changed.
+ * The DPI is the scale factor for a window. There are multiple events that can cause the DPI to
+ * change such as when the window is moved to a monitor with a different DPI.
+ */
+ {
+ WORD newYAxisDPI = HIWORD(wParam);
+ WORD newXAxisDPI = LOWORD(wParam);
+ // The suggested new size and position of the window.
+ RECT* const suggestedWindowRect = (RECT*)lParam;
+
+ // Push DPI change event first
+ system->pushEvent(processWindowEvent(GHOST_kEventWindowDPIHintChanged, window));
+ system->dispatchEvents();
+ eventHandled = true;
+
+ // Then move and resize window
+ SetWindowPos(hwnd,
+ NULL,
+ suggestedWindowRect->left,
+ suggestedWindowRect->top,
+ suggestedWindowRect->right - suggestedWindowRect->left,
+ suggestedWindowRect->bottom - suggestedWindowRect->top,
+ SWP_NOZORDER | SWP_NOACTIVATE);
+ }
+ break;
////////////////////////////////////////////////////////////////////////
// Window events, ignored
////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index d778628ea37..2798bdf72f3 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -295,6 +295,15 @@ public:
return 1.0f;
}
+ /**
+ * Returns the recommended DPI for this window.
+ * \return The recommended DPI for this window.
+ */
+ virtual inline GHOST_TUns16 getDPIHint()
+ {
+ return 96;
+ }
+
#ifdef WITH_INPUT_IME
virtual void beginIME(GHOST_TInt32 x,
GHOST_TInt32 y,
diff --git a/intern/ghost/intern/GHOST_WindowSDL.cpp b/intern/ghost/intern/GHOST_WindowSDL.cpp
index 1335c38d977..aeb6188daef 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.cpp
+++ b/intern/ghost/intern/GHOST_WindowSDL.cpp
@@ -563,3 +563,19 @@ GHOST_WindowSDL::setWindowCursorVisibility(bool visible)
SDL_ShowCursor(visible);
return GHOST_kSuccess;
}
+
+GHOST_TUns16
+GHOST_WindowSDL::getDPIHint()
+{
+ int displayIndex = SDL_GetWindowDisplayIndex(m_sdl_win);
+ if (displayIndex < 0) {
+ return 96;
+ }
+
+ float ddpi;
+ if (SDL_GetDisplayDPI(displayIndex, &ddpi, NULL, NULL) != 0) {
+ return 96;
+ }
+
+ return (int)ddpi;
+}
diff --git a/intern/ghost/intern/GHOST_WindowSDL.h b/intern/ghost/intern/GHOST_WindowSDL.h
index 5f658e8ad01..96104ec28b4 100644
--- a/intern/ghost/intern/GHOST_WindowSDL.h
+++ b/intern/ghost/intern/GHOST_WindowSDL.h
@@ -168,6 +168,8 @@ protected:
GHOST_TSuccess beginFullScreen() const { return GHOST_kFailure; }
GHOST_TSuccess endFullScreen() const { return GHOST_kFailure; }
+
+ GHOST_TUns16 getDPIHint();
};
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 58aa0b87045..2c82e3a3f71 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -92,6 +92,7 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
m_tablet(0),
m_maxPressure(0),
m_normal_state(GHOST_kWindowStateNormal),
+ m_user32(NULL),
m_parentWindowHwnd(parentwindowhwnd),
m_debug_context(is_debug)
{
@@ -905,6 +906,23 @@ void GHOST_WindowWin32::bringTabletContextToFront()
}
}
+GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
+{
+ if (!m_user32) {
+ m_user32 = ::LoadLibrary("user32.dll");
+ }
+
+ if (m_user32) {
+ GHOST_WIN32_GetDpiForWindow fpGetDpiForWindow = (GHOST_WIN32_GetDpiForWindow) ::GetProcAddress(m_user32, "GetDpiForWindow");
+
+ if (fpGetDpiForWindow) {
+ return fpGetDpiForWindow(this->m_hWnd);
+ }
+ }
+
+ return USER_DEFAULT_SCREEN_DPI;
+}
+
/** Reverse the bits in a GHOST_TUns8 */
static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)
{
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index a1cf58c9ceb..75a33951ff4 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -58,6 +58,12 @@ typedef BOOL (API * GHOST_WIN32_WTClose)(HCTX);
typedef BOOL (API * GHOST_WIN32_WTPacket)(HCTX, UINT, LPVOID);
typedef BOOL (API * GHOST_WIN32_WTOverlap)(HCTX, BOOL);
+// typedefs for user32 functions to allow dynamic loading of Windows 10 DPI scaling functions
+typedef UINT(API * GHOST_WIN32_GetDpiForWindow)(HWND);
+#ifndef USER_DEFAULT_SCREEN_DPI
+#define USER_DEFAULT_SCREEN_DPI 96
+#endif // USER_DEFAULT_SCREEN_DPI
+
/**
* GHOST window on M$ Windows OSs.
* \author Maarten Gribnau
@@ -251,6 +257,8 @@ public:
GHOST_TSuccess endFullScreen() const {return GHOST_kFailure;}
+ GHOST_TUns16 getDPIHint() override;
+
/** if the window currently resizing */
bool m_inLiveResize;
@@ -351,6 +359,9 @@ private:
GHOST_TWindowState m_normal_state;
+ /** user32 dll handle*/
+ HMODULE m_user32;
+
/** Hwnd to parent window */
GHOST_TEmbedderWindowID m_parentWindowHwnd;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 8cee785cdf6..f39f4f52289 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -56,6 +56,9 @@
# include <X11/extensions/XInput2.h>
#endif
+//For DPI value
+#include <X11/Xresource.h>
+
#if defined(__sun__) || defined(__sun) || defined(__sparc) || defined(__sparc__) || defined(_AIX)
# include <strings.h>
#endif
@@ -68,6 +71,7 @@
#include <algorithm>
#include <string>
+#include <math.h>
/* For obscure full screen mode stuff
* lifted verbatim from blut. */
@@ -1661,3 +1665,44 @@ endFullScreen() const
return GHOST_kSuccess;
}
+
+GHOST_TUns16
+GHOST_WindowX11::
+getDPIHint()
+{
+ /* Try to read DPI setting set using xrdb */
+ char* resMan = XResourceManagerString(m_display);
+ if (resMan) {
+ XrmDatabase xrdb = XrmGetStringDatabase(resMan);
+ if (xrdb) {
+ char* type = NULL;
+ XrmValue val;
+
+ int success = XrmGetResource(xrdb, "Xft.dpi", "Xft.Dpi", &type, &val);
+ if (success && type) {
+ if (strcmp(type, "String") == 0) {
+ return atoi((char*)val.addr);
+ }
+ }
+ }
+ }
+
+ /* Fallback to calculating DPI using X reported DPI, set using xrandr --dpi */
+ XWindowAttributes attr;
+ if (!XGetWindowAttributes(m_display, m_window, &attr)) {
+ /* Failed to get window attributes, return X11 default DPI */
+ return 96;
+ }
+
+ Screen* screen = attr.screen;
+ int pixelWidth = WidthOfScreen(screen);
+ int pixelHeight = HeightOfScreen(screen);
+ int mmWidth = WidthMMOfScreen(screen);
+ int mmHeight = HeightMMOfScreen(screen);
+
+ double pixelDiagonal = sqrt((pixelWidth * pixelWidth) + (pixelHeight * pixelHeight));
+ double mmDiagonal = sqrt((mmWidth * mmWidth) + (mmHeight * mmHeight));
+ float inchDiagonal = mmDiagonal * 0.039f;
+ int dpi = pixelDiagonal / inchDiagonal;
+ return dpi;
+}
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 9380aa9d631..5c54c1e8162 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -235,6 +235,8 @@ public:
GHOST_TSuccess endFullScreen() const;
+ GHOST_TUns16 getDPIHint();
+
protected:
/**
* \param type The type of rendering context create.
diff --git a/intern/ghost/test/CMakeLists.txt b/intern/ghost/test/CMakeLists.txt
index fb9ef621ecf..ef6e8915871 100644
--- a/intern/ghost/test/CMakeLists.txt
+++ b/intern/ghost/test/CMakeLists.txt
@@ -203,7 +203,6 @@ target_link_libraries(gears_c
glewmx_lib
string_lib
${OPENGL_gl_LIBRARY}
- ${OPENGL_glu_LIBRARY}
${PLATFORM_LINKLIBS}
)
@@ -217,7 +216,6 @@ target_link_libraries(gears_cpp
glewmx_lib
string_lib
${OPENGL_gl_LIBRARY}
- ${OPENGL_glu_LIBRARY}
${PLATFORM_LINKLIBS}
)
@@ -248,7 +246,6 @@ target_link_libraries(multitest_c
guardedalloc_lib
wcwidth_lib
${OPENGL_gl_LIBRARY}
- ${OPENGL_glu_LIBRARY}
${FREETYPE_LIBRARY}
${ZLIB_LIBRARIES}
${PLATFORM_LINKLIBS}
diff --git a/intern/libmv/libmv/numeric/numeric.h b/intern/libmv/libmv/numeric/numeric.h
index a42dab8c7a2..1a23d653676 100644
--- a/intern/libmv/libmv/numeric/numeric.h
+++ b/intern/libmv/libmv/numeric/numeric.h
@@ -36,7 +36,7 @@
#if !defined(__MINGW64__)
# if defined(_WIN32) || defined(__APPLE__) || \
defined(__FreeBSD__) || defined(__NetBSD__)
-static void sincos(double x, double *sinx, double *cosx) {
+inline void sincos(double x, double *sinx, double *cosx) {
*sinx = sin(x);
*cosx = cos(x);
}
diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt
index 61a8d995f40..f7e8d909f2c 100644
--- a/intern/opencolorio/CMakeLists.txt
+++ b/intern/opencolorio/CMakeLists.txt
@@ -66,6 +66,7 @@ if(WITH_OPENCOLORIO)
endif()
data_to_c_simple(gpu_shader_display_transform.glsl SRC)
+ data_to_c_simple(gpu_shader_display_transform_vertex.glsl SRC)
endif()
diff --git a/intern/opencolorio/gpu_shader_display_transform.glsl b/intern/opencolorio/gpu_shader_display_transform.glsl
index 853bf575582..4a63405045d 100644
--- a/intern/opencolorio/gpu_shader_display_transform.glsl
+++ b/intern/opencolorio/gpu_shader_display_transform.glsl
@@ -10,6 +10,15 @@ uniform float image_texture_width;
uniform float image_texture_height;
#endif
+#if __VERSION__ < 130
+ varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2D texture
+#endif
+
#ifdef USE_CURVE_MAPPING
/* Curve mapping parameters
*
@@ -143,7 +152,7 @@ vec4 apply_dither(vec2 st, vec4 col)
void main()
{
- vec4 col = texture2D(image_texture, gl_TexCoord[0].st);
+ vec4 col = texture2D(image_texture, texCoord_interp.st);
#ifdef USE_CURVE_MAPPING
col = curvemapping_evaluate_premulRGBF(col);
#endif
@@ -165,8 +174,8 @@ void main()
vec4 result = OCIODisplay(col, lut3d_texture);
#ifdef USE_DITHER
- result = apply_dither(gl_TexCoord[0].st, result);
+ result = apply_dither(texCoord_interp.st, result);
#endif
- gl_FragColor = result;
+ fragColor = result;
}
diff --git a/intern/opencolorio/gpu_shader_display_transform_vertex.glsl b/intern/opencolorio/gpu_shader_display_transform_vertex.glsl
new file mode 100644
index 00000000000..a6c00b080b2
--- /dev/null
+++ b/intern/opencolorio/gpu_shader_display_transform_vertex.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 texCoord;
+ attribute vec2 pos;
+ varying vec2 texCoord_interp;
+#else
+ in vec2 texCoord;
+ in vec2 pos;
+ out vec2 texCoord_interp;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f);
+ texCoord_interp = texCoord;
+}
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index bf91ea143da..9dba37f27eb 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -58,6 +58,7 @@ using namespace OCIO_NAMESPACE;
static const int LUT3D_EDGE_SIZE = 64;
extern "C" char datatoc_gpu_shader_display_transform_glsl[];
+extern "C" char datatoc_gpu_shader_display_transform_vertex_glsl[];
/* **** OpenGL drawing routines using GLSL for color space transform ***** */
@@ -89,6 +90,7 @@ typedef struct OCIO_GLSLDrawState {
/* GLSL stuff */
GLuint ocio_shader;
+ GLuint vert_shader;
GLuint program;
/* Previous OpenGL state. */
@@ -116,14 +118,15 @@ static GLuint compileShaderText(GLenum shaderType, const char *text)
return shader;
}
-static GLuint linkShaders(GLuint ocio_shader)
+static GLuint linkShaders(GLuint ocio_shader, GLuint vert_shader)
{
- if (!ocio_shader)
+ if (!ocio_shader || !vert_shader)
return 0;
GLuint program = glCreateProgram();
glAttachShader(program, ocio_shader);
+ glAttachShader(program, vert_shader);
glLinkProgram(program);
@@ -339,6 +342,25 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
glDeleteShader(state->ocio_shader);
}
+ if (state->vert_shader) {
+ glDeleteShader(state->vert_shader);
+ }
+
+ /* Vertex shader */
+ std::ostringstream osv;
+
+ if (supportGLSL13()) {
+ osv << "#version 130\n";
+ }
+ else {
+ osv << "#version 120\n";
+ }
+
+ osv << datatoc_gpu_shader_display_transform_vertex_glsl;
+
+ state->vert_shader = compileShaderText(GL_VERTEX_SHADER, osv.str().c_str());
+
+ /* Fragment shader */
std::ostringstream os;
if (supportGLSL13()) {
@@ -366,8 +388,8 @@ bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc
state->ocio_shader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str());
- if (state->ocio_shader) {
- state->program = linkShaders(state->ocio_shader);
+ if (state->ocio_shader && state->vert_shader) {
+ state->program = linkShaders(state->ocio_shader, state->vert_shader);
}
state->curve_mapping_used = use_curve_mapping;
diff --git a/make.bat b/make.bat
index 337a5517656..7a088a802f6 100644
--- a/make.bat
+++ b/make.bat
@@ -5,8 +5,8 @@ REM This is for users who like to configure & build Blender with a single comman
setlocal ENABLEEXTENSIONS
set BLENDER_DIR=%~dp0
set BLENDER_DIR_NOSPACES=%BLENDER_DIR: =%
-if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
- echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
+if not "%BLENDER_DIR%"=="%BLENDER_DIR_NOSPACES%" (
+ echo There are spaces detected in the build path "%BLENDER_DIR%", this is currently not supported, exiting....
goto EOF
)
set BUILD_DIR=%BLENDER_DIR%..\build_windows
@@ -79,7 +79,7 @@ if NOT "%1" == "" (
set NOBUILD=1
) else if "%1" == "showhash" (
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Branch_hash=%%i
- cd release/datafiles/locale
+ cd release/datafiles/locale
for /f "delims=" %%i in ('git rev-parse HEAD') do echo Locale_hash=%%i
cd %~dp0
cd release/scripts/addons
@@ -90,7 +90,7 @@ if NOT "%1" == "" (
) else if "%1" == "update" (
svn up ../lib/*
git pull --rebase
- git submodule foreach git pull --rebase origin master
+ git submodule update --remote
goto EOF
) else if "%1" == "clean" (
set MUST_CLEAN=1
@@ -132,13 +132,13 @@ if "%BUILD_ARCH%"=="x64" (
if "%target%"=="Release" (
- rem for vc12 check for both cuda 7.5 and 8
+ rem for vc12 check for both cuda 7.5 and 8
if "%CUDA_PATH%"=="" (
echo Cuda Not found, aborting!
goto EOF
)
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
- -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
+ -C"%BLENDER_DIR%\build_files\cmake\config\blender_release.cmake"
)
:DetectMSVC
@@ -157,7 +157,7 @@ if DEFINED MSVC_VC_DIR goto msvc_detect_finally
if DEFINED MSVC_VC_DIR call "%MSVC_VC_DIR%\vcvarsall.bat"
if DEFINED MSVC_VC_DIR goto sanity_checks
-rem MSVC Build environment 2017 and up.
+rem MSVC Build environment 2017 and up.
for /F "usebackq skip=2 tokens=1-2*" %%A IN (`REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SXS\VS7" /v %BUILD_VS_VER%.0 2^>nul`) DO set MSVC_VS_DIR=%%C
if DEFINED MSVC_VS_DIR goto msvc_detect_finally_2017
REM Check 32 bits
@@ -202,7 +202,7 @@ if NOT EXIST %BLENDER_DIR%..\lib\nul (
if "%TARGET%"=="" (
echo Error: Convenience target not set
echo This is required for building, aborting!
- echo .
+ echo .
goto HELP
)
@@ -266,15 +266,15 @@ echo.
echo At any point you can optionally modify your build configuration by editing:
echo "%BUILD_DIR%\CMakeCache.txt", then run "make" again to build with the changes applied.
echo.
-echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%"
+echo Blender successfully built, run from: "%BUILD_DIR%\bin\%BUILD_TYPE%\blender.exe"
echo.
goto EOF
:HELP
echo.
echo Convenience targets
- echo - release ^(identical to the offical blender.org builds^)
+ echo - release ^(identical to the official blender.org builds^)
echo - full ^(same as release minus the cuda kernels^)
- echo - lite
+ echo - lite
echo - headless
echo - cycles
echo - bpy
@@ -289,11 +289,10 @@ goto EOF
echo - with_tests ^(enable building unit tests^)
echo - debug ^(Build an unoptimized debuggable build^)
echo - packagename [newname] ^(override default cpack package name^)
- echo - x86 ^(override host autodetect and build 32 bit code^)
- echo - x64 ^(override host autodetect and build 64 bit code^)
+ echo - x86 ^(override host auto-detect and build 32 bit code^)
+ echo - x64 ^(override host auto-detect and build 64 bit code^)
echo - 2013 ^(build with visual studio 2013^)
echo - 2015 ^(build with visual studio 2015^) [EXPERIMENTAL]
echo.
:EOF
-
diff --git a/release/darwin/blender.app/Contents/Info.plist b/release/darwin/blender.app/Contents/Info.plist
index 36cb5d2ccaf..92e8d8cc761 100644
--- a/release/darwin/blender.app/Contents/Info.plist
+++ b/release/darwin/blender.app/Contents/Info.plist
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>LSMinimumSystemVersion</key>
- <string>10.7.0</string>
+ <string>10.9.0</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg
index e9c114ba1bd..d88788fa904 100644
--- a/release/datafiles/blender_icons.svg
+++ b/release/datafiles/blender_icons.svg
@@ -14,7 +14,7 @@
height="640"
id="svg2"
sodipodi:version="0.32"
- inkscape:version="0.91 r"
+ inkscape:version="0.91 r13725"
version="1.0"
sodipodi:docname="blender_icons.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
@@ -31338,6 +31338,26 @@
d="m 125.5,433.5 23,0 0,41 -33,0 0,-31 10,-10 z"
style="display:inline;fill:url(#linearGradient13110);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none" />
</clipPath>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient1610-6"
+ id="linearGradient18199"
+ gradientUnits="userSpaceOnUse"
+ x1="189.76083"
+ y1="248.13905"
+ x2="116.05637"
+ y2="183.6826" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient22562"
+ id="radialGradient23167-6"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0.99220964,-0.12457927,0.11585516,0.92272644,-34.13325,22.766225)"
+ cx="-0.78262758"
+ cy="294.63174"
+ fx="-0.78262758"
+ fy="294.63174"
+ r="6.6750002" />
</defs>
<sodipodi:namedview
id="base"
@@ -31349,16 +31369,16 @@
objecttolerance="10000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="14.413868"
- inkscape:cx="480.24726"
- inkscape:cy="269.95478"
+ inkscape:zoom="19.997864"
+ inkscape:cx="462.52244"
+ inkscape:cy="435.14241"
inkscape:document-units="px"
- inkscape:current-layer="layer1"
+ inkscape:current-layer="g23149-4"
showgrid="true"
- inkscape:window-width="1680"
- inkscape:window-height="1020"
- inkscape:window-x="0"
- inkscape:window-y="30"
+ inkscape:window-width="1920"
+ inkscape:window-height="1025"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
inkscape:snap-nodes="true"
inkscape:snap-bbox="true"
showguides="true"
@@ -92660,6 +92680,56 @@
style="opacity:0.51999996;fill:url(#radialGradient21448-8-143);fill-opacity:1;fill-rule:evenodd;stroke:none" />
</g>
</g>
+ <g
+ transform="translate(335.99871,21.048284)"
+ style="display:inline;enable-background:new"
+ id="ICON_ROTATE-7">
+ <rect
+ y="178"
+ x="110"
+ height="16"
+ width="16"
+ id="rect37989-8"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0;fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.79999995;marker:none;enable-background:accumulate" />
+ <path
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ id="path37498-7"
+ sodipodi:nodetypes="cccccccccccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccccccccccc"
+ id="rect38140-7"
+ d="m 114.5,192.5 -3,0 0,-3 m 13,0 0,3 -3,0 m -0.25,-13 3.25,0 0,3 m -13,0 0,-3 3,0"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:url(#linearGradient18199);stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:new"
+ inkscape:connector-curvature="0" />
+ <g
+ transform="matrix(0.59971056,0,0,0.59971056,116.78278,9.7425599)"
+ style="display:inline;enable-background:new"
+ id="g23145-9">
+ <g
+ id="g23149-4">
+ <path
+ id="path39832-9"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#1a1a1a;stroke-width:4.66725159;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="m -4.3682386,287.81345 1.5,0 c 0.999089,0 2.07885534,1.30514 2.50490386,2.78207 1.06592652,3.69512 2.80867074,9.82446 5.88525404,9.96406 2.6782554,0 1.6181317,-5.11535 3.1736046,-5.26275 l 0.25,0"
+ sodipodi:nodetypes="cssccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="ccscc"
+ d="m 9.3647983,295.22328 -0.4793018,0 c -2.2335161,0 0.1796731,4.94901 -3.4398065,5.09984 -4.44796752,0.18536 -5.37272213,-12.59185 -8.0767581,-12.56237 l -2,0"
+ style="display:inline;overflow:visible;visibility:visible;fill:none;stroke:#a8df84;stroke-width:2.93474906;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ id="path39834-2"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ id="path39836-9"
+ style="display:inline;overflow:visible;visibility:visible;opacity:0.35;fill:none;stroke:url(#radialGradient23167-6);stroke-width:3.53503864;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
+ d="M 5.6770841,300.48165 C 0.7393262,300.21066 0.54777814,287.99792 -2.9522219,287.99792"
+ sodipodi:nodetypes="cc"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat b/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat
new file mode 100644
index 00000000000..fe118a23d79
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_normalize_fcurves.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat b/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat
new file mode 100644
index 00000000000..5b1f546a563
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_normalize_fcurves.dat
Binary files differ
diff --git a/release/scripts/freestyle/modules/freestyle/shaders.py b/release/scripts/freestyle/modules/freestyle/shaders.py
index 633def38b5b..bce6642220b 100644
--- a/release/scripts/freestyle/modules/freestyle/shaders.py
+++ b/release/scripts/freestyle/modules/freestyle/shaders.py
@@ -568,7 +568,7 @@ class pyRandomColorShader(StrokeShader):
class py2DCurvatureColorShader(StrokeShader):
"""
- Assigns a color (greyscale) to the stroke based on the curvature.
+ Assigns a color (grayscale) to the stroke based on the curvature.
A higher curvature will yield a brighter color.
"""
def shade(self, stroke):
@@ -584,7 +584,7 @@ class py2DCurvatureColorShader(StrokeShader):
class pyTimeColorShader(StrokeShader):
"""
- Assigns a greyscale value that increases for every vertex.
+ Assigns a grayscale value that increases for every vertex.
The brightness will increase along the stroke.
"""
def __init__(self, step=0.01):
diff --git a/release/scripts/freestyle/modules/parameter_editor.py b/release/scripts/freestyle/modules/parameter_editor.py
index 93305cb7c5a..b093920a4cb 100644
--- a/release/scripts/freestyle/modules/parameter_editor.py
+++ b/release/scripts/freestyle/modules/parameter_editor.py
@@ -1170,6 +1170,7 @@ class Seed:
_seed = Seed()
+
def get_dashed_pattern(linestyle):
"""Extracts the dashed pattern from the various UI options """
pattern = []
@@ -1185,6 +1186,15 @@ def get_dashed_pattern(linestyle):
return pattern
+def get_grouped_objects(group):
+ for ob in group.objects:
+ if ob.dupli_type == 'GROUP' and ob.dupli_group is not None:
+ for dupli in get_grouped_objects(ob.dupli_group):
+ yield dupli
+ else:
+ yield ob
+
+
integration_types = {
'MEAN': IntegrationType.MEAN,
'MIN': IntegrationType.MIN,
@@ -1267,7 +1277,7 @@ def process(layer_name, lineset_name):
# prepare selection criteria by group of objects
if lineset.select_by_group:
if lineset.group is not None:
- names = {getQualifiedObjectName(ob): True for ob in lineset.group.objects}
+ names = {getQualifiedObjectName(ob): True for ob in get_grouped_objects(lineset.group)}
upred = ObjectNamesUP1D(names, lineset.group_negation == 'EXCLUSIVE')
selection_criteria.append(upred)
# prepare selection criteria by image border
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 0f096f5812c..51e3e65b78c 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -24,6 +24,7 @@ __all__ = (
"check",
"enable",
"disable",
+ "disable_all",
"reset_all",
"module_bl_info",
)
@@ -31,8 +32,9 @@ __all__ = (
import bpy as _bpy
_user_preferences = _bpy.context.user_preferences
-error_duplicates = False
error_encoding = False
+# (name, file, path)
+error_duplicates = []
addons_fake_modules = {}
@@ -57,12 +59,11 @@ def paths():
def modules_refresh(module_cache=addons_fake_modules):
- global error_duplicates
global error_encoding
import os
- error_duplicates = False
error_encoding = False
+ error_duplicates.clear()
path_list = paths()
@@ -168,7 +169,7 @@ def modules_refresh(module_cache=addons_fake_modules):
if mod.__file__ != mod_path:
print("multiple addons with the same name:\n %r\n %r" %
(mod.__file__, mod_path))
- error_duplicates = True
+ error_duplicates.append((mod.bl_info["name"], mod.__file__, mod_path))
elif mod.__time__ != os.path.getmtime(mod_path):
print("reloading addon:",
@@ -444,6 +445,13 @@ def reset_all(*, reload_scripts=False):
disable(mod_name)
+def disable_all():
+ import sys
+ for mod_name, mod in sys.modules.items():
+ if getattr(mod, "__addon_enabled__", False):
+ disable(mod_name)
+
+
def module_bl_info(mod, info_basis=None):
if info_basis is None:
info_basis = {
diff --git a/release/scripts/modules/bl_app_override/__init__.py b/release/scripts/modules/bl_app_override/__init__.py
new file mode 100644
index 00000000000..89cc8a0eb28
--- /dev/null
+++ b/release/scripts/modules/bl_app_override/__init__.py
@@ -0,0 +1,202 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+"""
+Module to manage overriding various parts of Blender.
+
+Intended for use with 'app_templates', though it can be used from anywhere.
+"""
+
+
+# TODO, how to check these aren't from add-ons.
+# templates might need to un-register while filtering.
+def class_filter(cls_parent, **kw):
+ whitelist = kw.pop("whitelist", None)
+ blacklist = kw.pop("blacklist", None)
+ kw_items = tuple(kw.items())
+ for cls in cls_parent.__subclasses__():
+ # same as is_registered()
+ if "bl_rna" in cls.__dict__:
+ if blacklist is not None and cls.__name__ in blacklist:
+ continue
+ if ((whitelist is not None and cls.__name__ is whitelist) or
+ all((getattr(cls, attr) in expect) for attr, expect in kw_items)):
+ yield cls
+
+
+def ui_draw_filter_register(
+ *,
+ ui_ignore_classes=None,
+ ui_ignore_operator=None,
+ ui_ignore_property=None,
+ ui_ignore_menu=None,
+ ui_ignore_label=None
+):
+ import bpy
+
+ UILayout = bpy.types.UILayout
+
+ if ui_ignore_classes is None:
+ ui_ignore_classes = (
+ bpy.types.Panel,
+ bpy.types.Menu,
+ bpy.types.Header,
+ )
+
+ class OperatorProperties_Fake:
+ pass
+
+ class UILayout_Fake(bpy.types.UILayout):
+ __slots__ = ()
+
+ def __getattribute__(self, attr):
+ # ensure we always pass down UILayout_Fake instances
+ if attr in {"row", "split", "column", "box", "column_flow"}:
+ real_func = UILayout.__getattribute__(self, attr)
+
+ def dummy_func(*args, **kw):
+ # print("wrapped", attr)
+ ret = real_func(*args, **kw)
+ return UILayout_Fake(ret)
+ return dummy_func
+
+ elif attr in {"operator", "operator_menu_enum", "operator_enum"}:
+ if ui_ignore_operator is None:
+ return UILayout.__getattribute__(self, attr)
+
+ real_func = UILayout.__getattribute__(self, attr)
+
+ def dummy_func(*args, **kw):
+ # print("wrapped", attr)
+ if not ui_ignore_operator(args[0]):
+ ret = real_func(*args, **kw)
+ else:
+ # UILayout.__getattribute__(self, "label")()
+ # may need to be set
+ ret = OperatorProperties_Fake()
+ return ret
+ return dummy_func
+
+ elif attr in {"prop", "prop_enum"}:
+ if ui_ignore_property is None:
+ return UILayout.__getattribute__(self, attr)
+
+ real_func = UILayout.__getattribute__(self, attr)
+
+ def dummy_func(*args, **kw):
+ # print("wrapped", attr)
+ if not ui_ignore_property(args[0].__class__.__name__, args[1]):
+ ret = real_func(*args, **kw)
+ else:
+ ret = None
+ return ret
+ return dummy_func
+
+ elif attr == "menu":
+ if ui_ignore_menu is None:
+ return UILayout.__getattribute__(self, attr)
+
+ real_func = UILayout.__getattribute__(self, attr)
+
+ def dummy_func(*args, **kw):
+ # print("wrapped", attr)
+ if not ui_ignore_menu(args[0]):
+ ret = real_func(*args, **kw)
+ else:
+ ret = None
+ return ret
+ return dummy_func
+
+ elif attr == "label":
+ if ui_ignore_label is None:
+ return UILayout.__getattribute__(self, attr)
+
+ real_func = UILayout.__getattribute__(self, attr)
+
+ def dummy_func(*args, **kw):
+ # print("wrapped", attr)
+ if not ui_ignore_label(args[0] if args else kw.get("text", "")):
+ ret = real_func(*args, **kw)
+ else:
+ # ret = real_func()
+ ret = None
+ return ret
+ return dummy_func
+ else:
+ return UILayout.__getattribute__(self, attr)
+ # print(self, attr)
+
+ def operator(*args, **kw):
+ return super().operator(*args, **kw)
+
+ def draw_override(func_orig, self_real, context):
+ cls_real = self_real.__class__
+ if cls_real is super:
+ # simple, no wrapping
+ return func_orig(self_real, context)
+
+ class Wrapper(cls_real):
+ __slots__ = ()
+ def __getattribute__(self, attr):
+ if attr == "layout":
+ return UILayout_Fake(self_real.layout)
+ else:
+ cls = super()
+ try:
+ return cls.__getattr__(self, attr)
+ except AttributeError:
+ # class variable
+ try:
+ return getattr(cls, attr)
+ except AttributeError:
+ # for preset bl_idname access
+ return getattr(UILayout(self), attr)
+
+ @property
+ def layout(self):
+ # print("wrapped")
+ return self_real.layout
+
+ return func_orig(Wrapper(self_real), context)
+
+ ui_ignore_store = []
+
+ for cls in ui_ignore_classes:
+ for subcls in list(cls.__subclasses__()):
+ if "draw" in subcls.__dict__: # don't want to get parents draw()
+
+ def replace_draw():
+ # function also serves to hold draw_old in a local name-space
+ draw_orig = subcls.draw
+
+ def draw(self, context):
+ return draw_override(draw_orig, self, context)
+ subcls.draw = draw
+
+ ui_ignore_store.append((subcls, "draw", subcls.draw))
+
+ replace_draw()
+
+ return ui_ignore_store
+
+
+def ui_draw_filter_unregister(ui_ignore_store):
+ for (obj, attr, value) in ui_ignore_store:
+ setattr(obj, attr, value)
diff --git a/release/scripts/modules/bl_app_override/helpers.py b/release/scripts/modules/bl_app_override/helpers.py
new file mode 100644
index 00000000000..981039e8ddc
--- /dev/null
+++ b/release/scripts/modules/bl_app_override/helpers.py
@@ -0,0 +1,167 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+# -----------------------------------------------------------------------------
+# AppOverrideState
+
+
+class AppOverrideState:
+ """
+ Utility class to encapsulate overriding the application state
+ so that settings can be restored afterwards.
+ """
+ __slots__ = (
+ # setup_classes
+ "_class_store",
+ # setup_ui_ignore
+ "_ui_ignore_store",
+ # setup_addons
+ "_addon_store",
+ )
+
+ # ---------
+ # Callbacks
+ #
+ # Set as None, to make it simple to check if they're being overridden.
+
+ # setup/teardown classes
+ class_ignore = None
+
+ # setup/teardown ui_ignore
+ ui_ignore_classes = None
+ ui_ignore_operator = None
+ ui_ignore_property = None
+ ui_ignore_menu = None
+ ui_ignore_label = None
+
+ addon_paths = None
+ addons = None
+
+ # End callbacks
+
+ def __init__(self):
+ self._class_store = None
+ self._addon_store = None
+ self._ui_ignore_store = None
+
+ def _setup_classes(self):
+ import bpy
+ assert(self._class_store is None)
+ self._class_store = self.class_ignore()
+ from bpy.utils import unregister_class
+ for cls in self._class_store:
+ unregister_class(cls)
+
+ def _teardown_classes(self):
+ assert(self._class_store is not None)
+
+ from bpy.utils import register_class
+ for cls in self._class_store:
+ register_class(cls)
+ self._class_store = None
+
+ def _setup_ui_ignore(self):
+ import bl_app_override
+
+ self._ui_ignore_store = bl_app_override.ui_draw_filter_register(
+ ui_ignore_classes=(
+ None if self.ui_ignore_classes is None
+ else self.ui_ignore_classes()
+ ),
+ ui_ignore_operator=self.ui_ignore_operator,
+ ui_ignore_property=self.ui_ignore_property,
+ ui_ignore_menu=self.ui_ignore_menu,
+ ui_ignore_label=self.ui_ignore_label,
+ )
+
+ def _teardown_ui_ignore(self):
+ import bl_app_override
+ bl_app_override.ui_draw_filter_unregister(
+ self._ui_ignore_store
+ )
+ self._ui_ignore_store = None
+
+ def _setup_addons(self):
+ import sys
+ import os
+
+ sys_path = []
+ if self.addon_paths is not None:
+ for path in self.addon_paths():
+ if path not in sys.path:
+ sys.path.append(path)
+
+ import addon_utils
+ addons = []
+ if self.addons is not None:
+ addons.extend(self.addons())
+ for addon in addons:
+ addon_utils.enable(addon)
+
+ self._addon_store = {
+ "sys_path": sys_path,
+ "addons": addons,
+ }
+
+ def _teardown_addons(self):
+ import sys
+
+ sys_path = self._addon_store["sys_path"]
+ for path in sys_path:
+ # should always succeed, but if not it doesn't matter
+ # (someone else was changing the sys.path), ignore!
+ try:
+ sys.path.remove(path)
+ except:
+ pass
+
+ addons = self._addon_store["addons"]
+ import addon_utils
+ for addon in addons:
+ addon_utils.disable(addon)
+
+ self._addon_store.clear()
+ self._addon_store = None
+
+ def setup(self):
+ if self.class_ignore is not None:
+ self._setup_classes()
+
+ if any((self.addon_paths,
+ self.addons,
+ )):
+ self._setup_addons()
+
+ if any((self.ui_ignore_operator,
+ self.ui_ignore_property,
+ self.ui_ignore_menu,
+ self.ui_ignore_label,
+ )):
+ self._setup_ui_ignore()
+
+ def teardown(self):
+ if self._class_store is not None:
+ self._teardown_classes()
+
+ if self._addon_store is not None:
+ self._teardown_addons()
+
+ if self._ui_ignore_store is not None:
+ self._teardown_ui_ignore()
diff --git a/release/scripts/modules/bl_app_template_utils.py b/release/scripts/modules/bl_app_template_utils.py
new file mode 100644
index 00000000000..b3a4824aa7b
--- /dev/null
+++ b/release/scripts/modules/bl_app_template_utils.py
@@ -0,0 +1,198 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+"""
+Similar to ``addon_utils``, except we can only have one active at a time.
+
+In most cases users of this module will simply call 'activate'.
+"""
+
+__all__ = (
+ "activate",
+ "import_from_path",
+ "import_from_id",
+ "reset",
+)
+
+import bpy as _bpy
+
+# Normally matches 'user_preferences.app_template_id',
+# but loading new preferences will get us out of sync.
+_app_template = {
+ "id": "",
+}
+
+# instead of sys.modules
+# note that we only ever have one template enabled at a time
+# so it may not seem necessary to use this.
+#
+# However, templates may want to share between each-other,
+# so any loaded modules are stored here?
+#
+# Note that the ID here is the app_template_id , not the modules __name__.
+_modules = {}
+
+
+def _enable(template_id, *, handle_error=None, ignore_not_found=False):
+ import os
+ import sys
+ from bpy_restrict_state import RestrictBlend
+
+ if handle_error is None:
+ def handle_error(ex):
+ import traceback
+ traceback.print_exc()
+
+ # Split registering up into 2 steps so we can undo
+ # if it fails par way through.
+
+ # disable the context, using the context at all is
+ # really bad while loading an template, don't do it!
+ with RestrictBlend():
+
+ # 1) try import
+ try:
+ mod = import_from_id(template_id, ignore_not_found=ignore_not_found)
+ if mod is None:
+ return None
+ mod.__template_enabled__ = False
+ _modules[template_id] = mod
+ except Exception as ex:
+ handle_error(ex)
+ return None
+
+ # 2) try run the modules register function
+ try:
+ mod.register()
+ except Exception as ex:
+ print("Exception in module register(): %r" %
+ getattr(mod, "__file__", template_id))
+ handle_error(ex)
+ del _modules[template_id]
+ return None
+
+ # * OK loaded successfully! *
+ mod.__template_enabled__ = True
+
+ if _bpy.app.debug_python:
+ print("\tapp_template_utils.enable", mod.__name__)
+
+ return mod
+
+
+def _disable(template_id, *, handle_error=None):
+ """
+ Disables a template by name.
+
+ :arg template_id: The name of the template and module.
+ :type template_id: string
+ :arg handle_error: Called in the case of an error,
+ taking an exception argument.
+ :type handle_error: function
+ """
+ import sys
+
+ if handle_error is None:
+ def handle_error(ex):
+ import traceback
+ traceback.print_exc()
+
+ mod = _modules.get(template_id)
+
+ if mod and getattr(mod, "__template_enabled__", False) is not False:
+ mod.__template_enabled__ = False
+
+ try:
+ mod.unregister()
+ except Exception as ex:
+ print("Exception in module unregister(): %r" %
+ getattr(mod, "__file__", template_id))
+ handle_error(ex)
+ else:
+ print("\tapp_template_utils.disable: %s not %s." %
+ (template_id, "disabled" if mod is None else "loaded"))
+
+ if _bpy.app.debug_python:
+ print("\tapp_template_utils.disable", template_id)
+
+
+def import_from_path(path, ignore_not_found=False):
+ import os
+ from importlib import import_module
+ base_module, template_id = path.rsplit(os.sep, 2)[-2:]
+ module_name = base_module + "." + template_id
+
+ try:
+ return import_module(module_name)
+ except ModuleNotFoundError as ex:
+ if ignore_not_found and ex.name == module_name:
+ return None
+ raise ex
+
+
+def import_from_id(template_id, ignore_not_found=False):
+ import os
+ path = next(iter(_bpy.utils.app_template_paths(template_id)), None)
+ if path is None:
+ if ignore_not_found:
+ return None
+ else:
+ raise Exception("%r template not found!" % template_id)
+ else:
+ if ignore_not_found:
+ if not os.path.exists(os.path.join(path, "__init__.py")):
+ return None
+ return import_from_path(path, ignore_not_found=ignore_not_found)
+
+
+def activate(template_id=None):
+ template_id_prev = _app_template["id"]
+
+ # not needed but may as well avoid activating same template
+ # ... in fact keep this, it will show errors early on!
+ """
+ if template_id_prev == template_id:
+ return
+ """
+
+ if template_id_prev:
+ _disable(template_id_prev)
+
+ # Disable all addons, afterwards caller must reset.
+ import addon_utils
+ addon_utils.disable_all()
+
+ # ignore_not_found so modules that don't contain scripts don't raise errors
+ mod = _enable(template_id, ignore_not_found=True) if template_id else None
+
+ _app_template["id"] = template_id
+
+
+def reset(*, reload_scripts=False):
+ """
+ Sets default state.
+ """
+ template_id = _bpy.context.user_preferences.app_template
+ if _bpy.app.debug_python:
+ print("bl_app_template_utils.reset('%s')" % template_id)
+
+ # TODO reload_scripts
+
+ activate(template_id)
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 26fdbc8cc56..545b891505f 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -48,11 +48,11 @@ def main():
import sys
# Possibly temp. addons path
- from os.path import join, dirname, normpath
- sys.path.append(normpath(join(dirname(__file__),
- "..", "..", "addons", "modules")))
- sys.path.append(join(utils.user_resource('SCRIPTS'),
- "addons", "modules"))
+ from os.path import join, dirname
+ sys.path.extend([
+ join(dirname(dirname(dirname(__file__))), "addons", "modules"),
+ join(utils.user_resource('SCRIPTS'), "addons", "modules"),
+ ])
# fake module to allow:
# from bpy.types import Panel
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index a864a86eba7..e17d710068c 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -204,7 +204,9 @@ def display_name(name):
name = name.replace("_colon_", ":")
name = name.replace("_plus_", "+")
- name = name.replace("_", " ")
+ # strip to allow underscore prefix
+ # (when paths can't start with numbers for eg).
+ name = name.replace("_", " ").lstrip(" ")
if name.islower():
name = name.lower().title()
diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py
index 31dd836e034..1d555ae7123 100644
--- a/release/scripts/modules/bpy/utils/__init__.py
+++ b/release/scripts/modules/bpy/utils/__init__.py
@@ -32,6 +32,7 @@ __all__ = (
"preset_find",
"preset_paths",
"refresh_script_paths",
+ "app_template_paths",
"register_class",
"register_module",
"register_manual_map",
@@ -49,18 +50,18 @@ __all__ = (
"unregister_class",
"unregister_module",
"user_resource",
- )
+)
from _bpy import (
- _utils_units as units,
- blend_paths,
- escape_identifier,
- register_class,
- resource_path,
- script_paths as _bpy_script_paths,
- unregister_class,
- user_resource as _user_resource,
- )
+ _utils_units as units,
+ blend_paths,
+ escape_identifier,
+ register_class,
+ resource_path,
+ script_paths as _bpy_script_paths,
+ unregister_class,
+ user_resource as _user_resource,
+)
import bpy as _bpy
import os as _os
@@ -142,7 +143,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
as modules.
:type refresh_scripts: bool
"""
- use_time = _bpy.app.debug_python
+ use_time = use_class_register_check = _bpy.app.debug_python
if use_time:
import time
@@ -161,7 +162,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
for module_name in [ext.module for ext in _user_preferences.addons]:
_addon_utils.disable(module_name)
- # *AFTER* unregistering all add-ons, otherwise all calls to unregister_module() will silently fail (do nothing).
+ # *AFTER* unregistering all add-ons, otherwise all calls to
+ # unregister_module() will silently fail (do nothing).
_bpy_types.TypeMap.clear()
def register_module_call(mod):
@@ -245,6 +247,12 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
+ # load template (if set)
+ if any(_bpy.utils.app_template_paths()):
+ import bl_app_template_utils
+ bl_app_template_utils.reset(reload_scripts=reload_scripts)
+ del bl_app_template_utils
+
# deal with addons separately
_initialize = getattr(_addon_utils, "_initialize", None)
if _initialize is not None:
@@ -269,13 +277,21 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if use_time:
print("Python Script Load Time %.4f" % (time.time() - t_main))
+ if use_class_register_check:
+ for cls in _bpy.types.bpy_struct.__subclasses__():
+ if getattr(cls, "is_registered", False):
+ for subcls in cls.__subclasses__():
+ if not subcls.is_registered:
+ print(
+ "Warning, unregistered class: %s(%s)" %
+ (subcls.__name__, cls.__name__)
+ )
+
# base scripts
-_scripts = _os.path.join(_os.path.dirname(__file__),
- _os.path.pardir,
- _os.path.pardir,
- )
-_scripts = (_os.path.normpath(_scripts), )
+_scripts = (
+ _os.path.dirname(_os.path.dirname(_os.path.dirname(__file__))),
+)
def script_path_user():
@@ -356,6 +372,38 @@ def refresh_script_paths():
_sys_path_ensure(path)
+def app_template_paths(subdir=None):
+ """
+ Returns valid application template paths.
+
+ :arg subdir: Optional subdir.
+ :type subdir: string
+ :return: app template paths.
+ :rtype: generator
+ """
+
+ # note: LOCAL, USER, SYSTEM order matches script resolution order.
+ subdir_tuple = (subdir,) if subdir is not None else ()
+
+ path = _os.path.join(*(
+ resource_path('LOCAL'), "scripts", "startup",
+ "bl_app_templates_user", *subdir_tuple))
+ if _os.path.isdir(path):
+ yield path
+ else:
+ path = _os.path.join(*(
+ resource_path('USER'), "scripts", "startup",
+ "bl_app_templates_user", *subdir_tuple))
+ if _os.path.isdir(path):
+ yield path
+
+ path = _os.path.join(*(
+ resource_path('SYSTEM'), "scripts", "startup",
+ "bl_app_templates_system", *subdir_tuple))
+ if _os.path.isdir(path):
+ yield path
+
+
def preset_paths(subdir):
"""
Returns a list of paths for a specific preset.
diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index d740137b0c3..83d3b2066b4 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -121,7 +121,14 @@ def object_data_add(context, obdata, operator=None, name=None):
"""
scene = context.scene
layer = context.render_layer
- scene_collection = context.scene_collection
+ layer_collection = context.layer_collection
+
+ if not layer_collection:
+ # when there is no collection linked to this render_layer create one
+ scene_collection = scene.master_collection.collections.new("")
+ layer_collection = layer.collections.link(scene_collection)
+ else:
+ scene_collection = layer_collection.collection
bpy.ops.object.select_all(action='DESELECT')
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index d64acd2ce3b..600b29a6b2b 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -683,6 +683,10 @@ class _GenericUI:
return draw_funcs
@classmethod
+ def is_extended(cls):
+ return bool(getattr(cls.draw, "_draw_funcs", None))
+
+ @classmethod
def append(cls, draw_func):
"""
Append a draw function to this menu,
@@ -725,11 +729,30 @@ class Header(StructRNA, _GenericUI, metaclass=RNAMeta):
class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
- def path_menu(self, searchpaths, operator,
- props_default=None, filter_ext=None):
+ def path_menu(self, searchpaths, operator, *,
+ props_default=None, prop_filepath="filepath",
+ filter_ext=None, filter_path=None, display_name=None):
+ """
+ Populate a menu from a list of paths.
+
+ :arg searchpaths: Paths to scan.
+ :type searchpaths: sequence of strings.
+ :arg operator: The operator id to use with each file.
+ :type operator: string
+ :arg prop_filepath: Optional operator filepath property (defaults to "filepath").
+ :type prop_filepath: string
+ :arg props_default: Properties to assign to each operator.
+ :type props_default: dict
+ :arg filter_ext: Optional callback that takes the file extensions.
+
+ Returning false excludes the file from the list.
+
+ :type filter_ext: Callable that takes a string and returns a bool.
+ :arg display_name: Optional callback that takes the full path, returns the name to display.
+ :type display_name: Callable that takes a string and returns a string.
+ """
layout = self.layout
- # hard coded to set the operators 'filepath' to the filename.
import os
import bpy.utils
@@ -742,25 +765,32 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
# collect paths
files = []
for directory in searchpaths:
- files.extend([(f, os.path.join(directory, f))
- for f in os.listdir(directory)
- if (not f.startswith("."))
- if ((filter_ext is None) or
- (filter_ext(os.path.splitext(f)[1])))
- ])
+ files.extend(
+ [(f, os.path.join(directory, f))
+ for f in os.listdir(directory)
+ if (not f.startswith("."))
+ if ((filter_ext is None) or
+ (filter_ext(os.path.splitext(f)[1])))
+ if ((filter_path is None) or
+ (filter_path(f)))
+ ])
files.sort()
for f, filepath in files:
- props = layout.operator(operator,
- text=bpy.path.display_name(f),
- translate=False)
+ # Intentionally pass the full path to 'display_name' callback,
+ # since the callback may want to use part a directory in the name.
+ props = layout.operator(
+ operator,
+ text=display_name(filepath) if display_name else bpy.path.display_name(f),
+ translate=False,
+ )
if props_default is not None:
for attr, value in props_default.items():
setattr(props, attr, value)
- props.filepath = filepath
+ setattr(props, prop_filepath, filepath)
if operator == "script.execute_preset":
props.menu_idname = self.bl_idname
diff --git a/release/scripts/modules/rna_keymap_ui.py b/release/scripts/modules/rna_keymap_ui.py
index 2ca7a7997a5..a1a4e5b8763 100644
--- a/release/scripts/modules/rna_keymap_ui.py
+++ b/release/scripts/modules/rna_keymap_ui.py
@@ -128,16 +128,15 @@ def draw_kmi(display_keymaps, kc, km, kmi, layout, level):
else:
box = col.column()
- split = box.split(percentage=0.01)
+ split = box.split()
# header bar
- row = split.row()
+ row = split.row(align=True)
row.prop(kmi, "show_expanded", text="", emboss=False)
-
- row = split.row()
row.prop(kmi, "active", text="", emboss=False)
if km.is_modal:
+ row.separator()
row.prop(kmi, "propvalue", text="")
else:
row.label(text=kmi.name)
diff --git a/release/scripts/presets/interface_theme/back_to_black.xml b/release/scripts/presets/interface_theme/back_to_black.xml
index 915e9cb64f1..1636f5b5cf6 100644
--- a/release/scripts/presets/interface_theme/back_to_black.xml
+++ b/release/scripts/presets/interface_theme/back_to_black.xml
@@ -18,7 +18,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_regular>
<wcol_tool>
@@ -30,19 +30,19 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_tool>
<wcol_radio>
<ThemeWidgetColors outline="#2a2a2a"
inner="#111111ff"
inner_sel="#33406bff"
- item="#191919ff"
+ item="#444444ff"
text="#929292"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_radio>
<wcol_text>
@@ -50,23 +50,23 @@
inner="#111111ff"
inner_sel="#33406bff"
item="#191919ff"
- text="#e4e4e4"
+ text="#929292"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_text>
<wcol_option>
- <ThemeWidgetColors outline="#2a2a2a"
+ <ThemeWidgetColors outline="#535353"
inner="#111111ff"
inner_sel="#33406bff"
- item="#000000ff"
- text="#c7c7c7"
+ item="#a3a3a3ff"
+ text="#929292"
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_option>
<wcol_toggle>
@@ -78,7 +78,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_toggle>
<wcol_num>
@@ -90,7 +90,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_num>
<wcol_numslider>
@@ -102,7 +102,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_numslider>
<wcol_box>
@@ -114,7 +114,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_box>
<wcol_menu>
@@ -126,7 +126,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_menu>
<wcol_pulldown>
@@ -138,7 +138,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_pulldown>
<wcol_menu_back>
@@ -150,7 +150,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_menu_back>
<wcol_pie_menu>
@@ -170,7 +170,7 @@
inner="#191919e6"
inner_sel="#2d2d2de6"
item="#646464ff"
- text="#ffffff"
+ text="#929292"
text_sel="#ffffff"
show_shaded="FALSE"
shadetop="25"
@@ -186,7 +186,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_menu_item>
<wcol_scroll>
@@ -198,7 +198,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_scroll>
<wcol_progress>
@@ -210,7 +210,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_progress>
<wcol_list_item>
@@ -222,7 +222,7 @@
text_sel="#ffffff"
show_shaded="TRUE"
shadetop="-100"
- shadedown="0">
+ shadedown="5">
</ThemeWidgetColors>
</wcol_list_item>
<wcol_state>
@@ -239,32 +239,35 @@
</user_interface>
<view_3d>
<ThemeView3D grid="#222222"
+ clipping_border_3d="#313131ff"
wire="#888888"
- wire_edit="#000000"
+ wire_edit="#6c75ff"
gp_vertex="#000000"
gp_vertex_select="#ff8500"
gp_vertex_size="3"
- lamp="#c1d40028"
- speaker="#535353"
- camera="#000000"
- view_overlay="#000000"
- empty="#000000"
+ text_grease_pencil="#b5e61d"
object_selected="#f15800"
object_active="#ff8c19"
object_grouped="#083008"
object_grouped_active="#55bb55"
- transform="#ffffff"
+ text_keyframe="#ddd700"
+ camera="#535353"
+ empty="#535353"
+ lamp="#fff0d328"
+ speaker="#535353"
vertex="#72cfdd"
vertex_select="#ff8500"
vertex_size="3"
+ vertex_bevel="#00a5ff"
vertex_unreferenced="#000000"
edge_select="#ffa000"
edge_seam="#db2512"
edge_sharp="#ff2020"
edge_crease="#cc0099"
+ edge_bevel="#00a5ff"
edge_facesel="#6b6b6b"
freestyle_edge_mark="#7fff7f"
- face="#73828f12"
+ face="#73828f41"
face_select="#ffa4003c"
face_dot="#ffa900"
facedot_size="4"
@@ -291,19 +294,18 @@
normal="#22dddd"
vertex_normal="#2361dd"
split_normal="#dd23dd"
- bone_solid="#c8c8c8"
bone_pose="#50c8ff"
bone_pose_active="#8cffff"
- frame_current="#60c040"
- outline_width="1"
+ bone_solid="#c8c8c8"
bundle_solid="#c8c8c8"
camera_path="#5a5a5a"
skin_root="#000000"
- clipping_border_3d="#313131ff"
- text_keyframe="#ddd700"
- text_grease_pencil="#b5e61d"
+ view_overlay="#000000"
+ transform="#ffffff"
+ frame_current="#60c040"
paint_curve_handle="#7fff7f7f"
- paint_curve_pivot="#ff7f7f7f">
+ paint_curve_pivot="#ff7f7f7f"
+ outline_width="1">
<space>
<ThemeSpaceGradient title="#5d5d5d"
text="#7d7d7d"
@@ -312,23 +314,23 @@
header_text="#979797"
header_text_hi="#ffffff"
button="#00000057"
- button_title="#c5c5c5"
+ button_title="#929292"
button_text="#c3c3c3"
- button_text_hi="#ffffff"
+ button_text_hi="#e5e5e5"
tab_active="#212947"
tab_inactive="#000000"
tab_back="#060606ff"
tab_outline="#000000">
<gradients>
<ThemeGradientColors show_grad="TRUE"
- gradient="#0a0a0a"
+ gradient="#1d1d1d"
high_gradient="#000000">
</ThemeGradientColors>
</gradients>
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -348,6 +350,7 @@
vertex="#ffffff"
vertex_select="#ff8500"
vertex_size="3"
+ vertex_bevel="#000000"
vertex_unreferenced="#000000"
handle_free="#808080"
handle_auto="#909000"
@@ -382,7 +385,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -418,7 +421,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -463,7 +466,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -501,6 +504,7 @@
keyframe_jitter_selected="#61c042"
keyframe_border="#000000ff"
keyframe_border_selected="#000000ff"
+ keyframe_scale_factor="1"
summary="#00000000">
<space>
<ThemeSpaceGeneric back="#080808"
@@ -521,7 +525,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -543,6 +547,7 @@
vertex="#0f13bb"
vertex_select="#ff8500"
vertex_size="3"
+ vertex_bevel="#000000"
vertex_unreferenced="#000000"
face="#ffffff0a"
face_select="#ff85003c"
@@ -596,7 +601,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -644,7 +649,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -673,7 +678,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -712,7 +717,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -744,7 +749,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -799,7 +804,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -835,7 +840,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -865,7 +870,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -903,7 +908,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -932,7 +937,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -966,7 +971,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
@@ -1019,7 +1024,7 @@
<panelcolors>
<ThemePanelColors header="#00000019"
back="#72727280"
- show_header="FALSE"
+ show_header="TRUE"
show_back="FALSE">
</ThemePanelColors>
</panelcolors>
diff --git a/release/scripts/presets/keyconfig/3dsmax.py b/release/scripts/presets/keyconfig/3dsmax.py
index b6b0a0c926f..09c6704df1f 100644
--- a/release/scripts/presets/keyconfig/3dsmax.py
+++ b/release/scripts/presets/keyconfig/3dsmax.py
@@ -7,7 +7,7 @@ kc = wm.keyconfigs.new('3dsmax')
# Map Window
km = kc.keymaps.new('Window', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('wm.window_duplicate', 'W', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.window_new', 'W', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('wm.read_homefile', 'N', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.save_homefile', 'U', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
@@ -400,6 +400,12 @@ kmi = km.keymap_items.new('particle.hide', 'H', 'PRESS')
kmi.properties.unselected = False
kmi = km.keymap_items.new('particle.hide', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_planar_constraint= True
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_accurate= True
kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True
kmi = km.keymap_items.new('particle.brush_edit', 'LEFTMOUSE', 'PRESS')
@@ -421,6 +427,12 @@ kmi.properties.value_2 = 'ENABLED'
# Map 3D View
km = kc.keymaps.new('3D View', space_type='VIEW_3D', region_type='WINDOW', modal=False)
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_planar_constraint= True
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_accurate= True
kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True
kmi = km.keymap_items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index f542ecf810b..194b9b3c283 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -8,7 +8,7 @@ kc = wm.keyconfigs.new(os.path.splitext(os.path.basename(__file__))[0])
# Map Window
km = kc.keymaps.new('Window', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.keymap_items.new('wm.window_duplicate', 'W', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('wm.window_new', 'W', 'PRESS', ctrl=True, alt=True)
kmi = km.keymap_items.new('wm.read_homefile', 'N', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.save_homefile', 'U', 'PRESS', ctrl=True)
kmi = km.keymap_items.new('wm.call_menu', 'O', 'PRESS', shift=True, ctrl=True)
@@ -932,6 +932,12 @@ km = kc.keymaps.new('3D View', space_type='VIEW_3D', region_type='WINDOW', modal
kmi = km.keymap_items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
kmi = km.keymap_items.new('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_planar_constraint = True
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', shift=True)
+kmi.properties.release_confirm = True
+kmi.properties.use_accurate = True
kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True
kmi = km.keymap_items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
index a696410ca1c..1e0dbe6925e 100644
--- a/release/scripts/startup/bl_operators/__init__.py
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -21,8 +21,7 @@
# support reloading sub-modules
if "bpy" in locals():
from importlib import reload
- for val in _modules_loaded:
- reload(val)
+ _modules_loaded[:] = [reload(val) for val in _modules_loaded]
del reload
_modules = [
@@ -63,8 +62,15 @@ del _namespace
def register():
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for mod in _modules_loaded:
+ for cls in mod.classes:
+ register_class(cls)
def unregister():
- bpy.utils.unregister_module(__name__)
+ from bpy.utils import unregister_class
+ for mod in reversed(_modules_loaded):
+ for cls in reversed(mod.classes):
+ if cls.is_registered:
+ unregister_class(cls)
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 247b91e147f..0e5acea94f9 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -282,3 +282,8 @@ class AddTorus(Operator, object_utils.AddObjectHelper):
object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
+
+
+classes = (
+ AddTorus,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/anim.py b/release/scripts/startup/bl_operators/anim.py
index c20d591241c..78fcf0dd124 100644
--- a/release/scripts/startup/bl_operators/anim.py
+++ b/release/scripts/startup/bl_operators/anim.py
@@ -28,11 +28,11 @@ if "bpy" in locals():
import bpy
from bpy.types import Operator
from bpy.props import (
- IntProperty,
- BoolProperty,
- EnumProperty,
- StringProperty,
- )
+ IntProperty,
+ BoolProperty,
+ EnumProperty,
+ StringProperty,
+)
class ANIM_OT_keying_set_export(Operator):
@@ -115,30 +115,30 @@ class ANIM_OT_keying_set_export(Operator):
# Find material or lamp using this node tree...
id_bpy_path = "bpy.data.nodes[\"%s\"]"
found = False
-
+
for mat in bpy.data.materials:
if mat.node_tree == ksp.id:
id_bpy_path = "bpy.data.materials[\"%s\"].node_tree" % (mat.name)
found = True
- break;
-
+ break
+
if not found:
for lamp in bpy.data.lamps:
if lamp.node_tree == ksp.id:
id_bpy_path = "bpy.data.lamps[\"%s\"].node_tree" % (lamp.name)
found = True
- break;
-
+ break
+
if not found:
- self.report({'WARN'}, "Could not find material or lamp using Shader Node Tree - %s" % (ksp.id))
+ self.report({'WARN'}, "Could not find material or lamp using Shader Node Tree - %s" % (ksp.id))
elif ksp.id.bl_rna.identifier.startswith("CompositorNodeTree"):
# Find compositor nodetree using this node tree...
for scene in bpy.data.scenes:
if scene.node_tree == ksp.id:
id_bpy_path = "bpy.data.scenes[\"%s\"].node_tree" % (scene.name)
- break;
+ break
else:
- self.report({'WARN'}, "Could not find scene using Compositor Node Tree - %s" % (ksp.id))
+ self.report({'WARN'}, "Could not find scene using Compositor Node Tree - %s" % (ksp.id))
else:
idtype_list = ksp.id.bl_rna.name.lower() + "s"
id_bpy_path = "bpy.data.%s[\"%s\"]" % (idtype_list, ksp.id.name)
@@ -302,9 +302,11 @@ class ClearUselessActions(Operator):
bl_label = "Clear Useless Actions"
bl_options = {'REGISTER', 'UNDO'}
- only_unused = BoolProperty(name="Only Unused",
+ only_unused = BoolProperty(
+ name="Only Unused",
description="Only unused (Fake User only) actions get considered",
- default=True)
+ default=True,
+ )
@classmethod
def poll(cls, context):
@@ -393,7 +395,7 @@ class UpdateAnimatedTransformConstraint(Operator):
except:
pass
ret = (data, new_path)
- #print(ret)
+ # print(ret)
return ret
@@ -412,3 +414,11 @@ class UpdateAnimatedTransformConstraint(Operator):
text.from_string(log)
self.report({'INFO'}, "Complete report available on '%s' text datablock" % text.name)
return {'FINISHED'}
+
+
+classes = (
+ ANIM_OT_keying_set_export,
+ BakeAction,
+ ClearUselessActions,
+ UpdateAnimatedTransformConstraint,
+)
diff --git a/release/scripts/startup/bl_operators/clip.py b/release/scripts/startup/bl_operators/clip.py
index d60703236d6..6747bfec1fb 100644
--- a/release/scripts/startup/bl_operators/clip.py
+++ b/release/scripts/startup/bl_operators/clip.py
@@ -21,7 +21,10 @@ import bpy
import os
from bpy.types import Operator
from bpy.props import FloatProperty
-from mathutils import Vector, Matrix
+from mathutils import (
+ Vector,
+ Matrix,
+)
def CLIP_spaces_walk(context, all_screens, tarea, tspace, callback, *args):
@@ -1071,3 +1074,17 @@ class CLIP_OT_track_settings_to_track(bpy.types.Operator):
setattr(marker_selected, attr, getattr(marker, attr))
return {'FINISHED'}
+
+
+classes = (
+ CLIP_OT_bundles_to_mesh,
+ CLIP_OT_constraint_to_fcurve,
+ CLIP_OT_delete_proxy,
+ CLIP_OT_filter_tracks,
+ CLIP_OT_set_active_clip,
+ CLIP_OT_set_viewport_background,
+ CLIP_OT_setup_tracking_scene,
+ CLIP_OT_track_settings_as_default,
+ CLIP_OT_track_settings_to_track,
+ CLIP_OT_track_to_empty,
+)
diff --git a/release/scripts/startup/bl_operators/console.py b/release/scripts/startup/bl_operators/console.py
index 8cfc977294a..fb36f80239e 100644
--- a/release/scripts/startup/bl_operators/console.py
+++ b/release/scripts/startup/bl_operators/console.py
@@ -159,3 +159,12 @@ class ConsoleLanguage(Operator):
remove_duplicates=True)
return {'FINISHED'}
+
+
+classes = (
+ ConsoleAutocomplete,
+ ConsoleBanner,
+ ConsoleCopyAsScript,
+ ConsoleExec,
+ ConsoleLanguage,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/file.py b/release/scripts/startup/bl_operators/file.py
index 51e079164b6..d710b9af715 100644
--- a/release/scripts/startup/bl_operators/file.py
+++ b/release/scripts/startup/bl_operators/file.py
@@ -248,3 +248,8 @@ class WM_OT_previews_batch_clear(Operator):
return {'FINISHED'}
+
+classes = (
+ WM_OT_previews_batch_clear,
+ WM_OT_previews_batch_generate,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/freestyle.py b/release/scripts/startup/bl_operators/freestyle.py
index 43cd3110beb..4cee1abf15f 100644
--- a/release/scripts/startup/bl_operators/freestyle.py
+++ b/release/scripts/startup/bl_operators/freestyle.py
@@ -16,13 +16,15 @@
#
# ##### END GPL LICENSE BLOCK #####
+# <pep8 compliant>
+
import bpy
from bpy.props import (
- BoolProperty,
- EnumProperty,
- StringProperty,
- )
+ BoolProperty,
+ EnumProperty,
+ StringProperty,
+)
class SCENE_OT_freestyle_fill_range_by_selection(bpy.types.Operator):
@@ -218,3 +220,11 @@ class SCENE_OT_freestyle_module_open(bpy.types.Operator):
text = bpy.data.texts.load(self.filepath, self.make_internal)
self.freestyle_module.script = text
return {'FINISHED'}
+
+
+classes = (
+ SCENE_OT_freestyle_add_edge_marks_to_keying_set,
+ SCENE_OT_freestyle_add_face_marks_to_keying_set,
+ SCENE_OT_freestyle_fill_range_by_selection,
+ SCENE_OT_freestyle_module_open,
+)
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index d3460383fe7..6a538f0ae33 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -242,3 +242,11 @@ class ProjectApply(Operator):
bpy.ops.paint.project_image(image=image_name)
return {'FINISHED'}
+
+
+classes = (
+ EditExternally,
+ ProjectApply,
+ ProjectEdit,
+ SaveDirty,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/mask.py b/release/scripts/startup/bl_operators/mask.py
index aa984659430..78a4bd9af27 100644
--- a/release/scripts/startup/bl_operators/mask.py
+++ b/release/scripts/startup/bl_operators/mask.py
@@ -31,3 +31,8 @@ class MASK_MT_add(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("mask.primitive_circle_add", text="Circle", icon='MESH_CIRCLE')
layout.operator("mask.primitive_square_add", text="Square", icon='MESH_PLANE')
+
+
+classes = (
+ MASK_MT_add,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index 58eab5436e6..4edefd7bf9b 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -21,7 +21,10 @@
import bpy
from bpy.types import Operator
-from bpy.props import EnumProperty, IntProperty
+from bpy.props import (
+ EnumProperty,
+ IntProperty,
+)
class MeshMirrorUV(Operator):
@@ -248,3 +251,10 @@ class MehsSetNormalsFromFaces(Operator):
return {'FINISHED'}
+
+classes = (
+ MehsSetNormalsFromFaces,
+ MeshMirrorUV,
+ MeshSelectNext,
+ MeshSelectPrev,
+)
diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index acff259e503..40876e2b069 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -21,16 +21,16 @@
import bpy
import nodeitems_utils
from bpy.types import (
- Operator,
- PropertyGroup,
- )
+ Operator,
+ PropertyGroup,
+)
from bpy.props import (
- BoolProperty,
- CollectionProperty,
- EnumProperty,
- IntProperty,
- StringProperty,
- )
+ BoolProperty,
+ CollectionProperty,
+ EnumProperty,
+ IntProperty,
+ StringProperty,
+)
class NodeSetting(PropertyGroup):
@@ -295,3 +295,14 @@ class NODE_OT_tree_path_parent(Operator):
space.path.pop()
return {'FINISHED'}
+
+
+classes = (
+ NodeSetting,
+
+ NODE_OT_add_and_link_node,
+ NODE_OT_add_node,
+ NODE_OT_add_search,
+ NODE_OT_collapse_hide_unused_toggle,
+ NODE_OT_tree_path_parent,
+)
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index be680a6df0c..b730e866323 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -21,12 +21,12 @@
import bpy
from bpy.types import Operator
from bpy.props import (
- StringProperty,
- BoolProperty,
- EnumProperty,
- IntProperty,
- FloatProperty,
- )
+ BoolProperty,
+ EnumProperty,
+ FloatProperty,
+ IntProperty,
+ StringProperty,
+)
class SelectPattern(Operator):
@@ -1036,3 +1036,22 @@ class LodGenerate(Operator):
scene.objects.active = ob
return {'FINISHED'}
+
+
+classes = (
+ ClearAllRestrictRender,
+ DupliOffsetFromCursor,
+ IsolateTypeRender,
+ JoinUVs,
+ LodByName,
+ LodClearAll,
+ LodGenerate,
+ MakeDupliFace,
+ SelectCamera,
+ SelectHierarchy,
+ SelectPattern,
+ ShapeTransfer,
+ SubdivisionSet,
+ TransformsToDeltas,
+ TransformsToDeltasAnim,
+)
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index a6ee16e6b71..1539ffb3545 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -26,13 +26,14 @@ from mathutils import Vector
def GlobalBB_LQ(bb_world):
# Initialize the variables with the 8th vertex
- left, right, front, back, down, up = (bb_world[7][0],
- bb_world[7][0],
- bb_world[7][1],
- bb_world[7][1],
- bb_world[7][2],
- bb_world[7][2],
- )
+ left, right, front, back, down, up = (
+ bb_world[7][0],
+ bb_world[7][0],
+ bb_world[7][1],
+ bb_world[7][1],
+ bb_world[7][2],
+ bb_world[7][2],
+ )
# Test against the other 7 verts
for i in range(7):
@@ -398,16 +399,23 @@ class AlignObjects(Operator):
def execute(self, context):
align_axis = self.align_axis
- ret = align_objects(context,
- 'X' in align_axis,
- 'Y' in align_axis,
- 'Z' in align_axis,
- self.align_mode,
- self.relative_to,
- self.bb_quality)
+ ret = align_objects(
+ context,
+ 'X' in align_axis,
+ 'Y' in align_axis,
+ 'Z' in align_axis,
+ self.align_mode,
+ self.relative_to,
+ self.bb_quality,
+ )
if not ret:
self.report({'WARNING'}, "No objects with bound-box selected")
return {'CANCELLED'}
else:
return {'FINISHED'}
+
+
+classes = (
+ AlignObjects,
+)
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index ef10e279bb4..16f29c77bb9 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -22,12 +22,12 @@ from mathutils import Vector
import bpy
from bpy.types import Operator
from bpy.props import (
- BoolProperty,
- EnumProperty,
- IntProperty,
- FloatProperty,
- FloatVectorProperty,
- )
+ BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+)
def object_ensure_material(obj, mat_name):
@@ -319,7 +319,7 @@ class QuickSmoke(Operator):
def execute(self, context):
if not bpy.app.build_options.mod_smoke:
- self.report({'ERROR'}, "Build without Smoke modifier support")
+ self.report({'ERROR'}, "Built without Smoke modifier support")
return {'CANCELLED'}
fake_context = context.copy()
@@ -568,7 +568,7 @@ class QuickFluid(Operator):
def execute(self, context):
if not bpy.app.build_options.mod_fluid:
- self.report({'ERROR'}, "Build without Fluid modifier support")
+ self.report({'ERROR'}, "Built without Fluid modifier support")
return {'CANCELLED'}
fake_context = context.copy()
@@ -645,3 +645,11 @@ class QuickFluid(Operator):
bpy.ops.fluid.bake('INVOKE_DEFAULT')
return {'FINISHED'}
+
+
+classes = (
+ QuickExplode,
+ QuickFluid,
+ QuickFur,
+ QuickSmoke,
+)
diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index 38110328603..f856b85844e 100644
--- a/release/scripts/startup/bl_operators/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -185,3 +185,8 @@ class RandomizeLocRotSize(Operator):
loc, rot, scale, scale_even, scale_min)
return {'FINISHED'}
+
+
+classes = (
+ RandomizeLocRotSize,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index e01e509b292..fdacf24f6e0 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -135,7 +135,7 @@ class AddPresetBase:
file_preset.write("%s = %r\n" % (rna_path_step, value))
- file_preset = open(filepath, 'w')
+ file_preset = open(filepath, 'w', encoding="utf-8")
file_preset.write("import bpy\n")
if hasattr(self, "preset_defines"):
@@ -680,3 +680,26 @@ class AddPresetUnitsLength(AddPresetBase, Operator):
]
preset_subdir = "units_length"
+
+
+classes = (
+ AddPresetCamera,
+ AddPresetCloth,
+ AddPresetFluid,
+ AddPresetHairDynamics,
+ AddPresetInteraction,
+ AddPresetInterfaceTheme,
+ AddPresetKeyconfig,
+ AddPresetNodeColor,
+ AddPresetOperator,
+ AddPresetRender,
+ AddPresetSSS,
+ AddPresetSafeAreas,
+ AddPresetSunSky,
+ AddPresetTrackingCamera,
+ AddPresetTrackingSettings,
+ AddPresetTrackingTrackColor,
+ AddPresetUnitsLength,
+ ExecutePreset,
+ WM_MT_operator_presets,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/rigidbody.py b/release/scripts/startup/bl_operators/rigidbody.py
index cba49c629be..e10a2a2915e 100644
--- a/release/scripts/startup/bl_operators/rigidbody.py
+++ b/release/scripts/startup/bl_operators/rigidbody.py
@@ -20,8 +20,10 @@
import bpy
from bpy.types import Operator
-from bpy.props import IntProperty
-from bpy.props import EnumProperty
+from bpy.props import (
+ EnumProperty,
+ IntProperty,
+)
class CopyRigidbodySettings(Operator):
@@ -309,3 +311,10 @@ class ConnectRigidBodies(Operator):
else:
self.report({'WARNING'}, "No other objects selected")
return {'CANCELLED'}
+
+
+classes = (
+ BakeToKeyframes,
+ ConnectRigidBodies,
+ CopyRigidbodySettings,
+)
diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
index a5565699364..f4d6c7065a9 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -180,3 +180,8 @@ class PlayRenderedAnim(Operator):
return {'CANCELLED'}
return {'FINISHED'}
+
+
+classes = (
+ PlayRenderedAnim,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index 31ca4249a9d..7209b6b478f 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -134,3 +134,10 @@ class SequencerDeinterlaceSelectedMovies(Operator):
s.use_deinterlace = True
return {'FINISHED'}
+
+
+classes = (
+ SequencerCrossfadeSounds,
+ SequencerCutMulticam,
+ SequencerDeinterlaceSelectedMovies,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index d1ac9e0b586..25ee5cafe81 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -248,3 +248,8 @@ class FollowActiveQuads(Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
+
+
+classes = (
+ FollowActiveQuads,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 3b095c883a3..8ee29d15d1b 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -668,3 +668,8 @@ class LightMapPack(Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
+
+
+classes = (
+ LightMapPack,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 52e7b0e0ae4..5581415c083 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -18,7 +18,11 @@
# TODO <pep8 compliant>
-from mathutils import Matrix, Vector, geometry
+from mathutils import (
+ Matrix,
+ Vector,
+ geometry,
+)
import bpy
from bpy.types import Operator
@@ -1100,3 +1104,8 @@ class SmartProject(Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
+
+
+classes = (
+ SmartProject,
+)
diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 892e1822d68..c006e8e6e92 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -182,3 +182,8 @@ class VertexPaintDirt(Operator):
ret = applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, self.dirt_angle, self.clean_angle, self.dirt_only)
return ret
+
+
+classes = (
+ VertexPaintDirt,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/view3d.py b/release/scripts/startup/bl_operators/view3d.py
index df4a93bb87f..acec2d8fe91 100644
--- a/release/scripts/startup/bl_operators/view3d.py
+++ b/release/scripts/startup/bl_operators/view3d.py
@@ -213,3 +213,11 @@ class VIEW3D_OT_select_or_deselect_all(Operator):
enumerate=self.enumerate,
object=self.object,
location=(x, y))
+
+
+classes = (
+ VIEW3D_OT_edit_mesh_extrude_individual_move,
+ VIEW3D_OT_edit_mesh_extrude_move,
+ VIEW3D_OT_edit_mesh_extrude_shrink_fatten,
+ VIEW3D_OT_select_or_deselect_all,
+) \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index f5460d58d44..d94951341c1 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -21,12 +21,12 @@
import bpy
from bpy.types import Operator
from bpy.props import (
- StringProperty,
- BoolProperty,
- IntProperty,
- FloatProperty,
- EnumProperty,
- )
+ StringProperty,
+ BoolProperty,
+ IntProperty,
+ FloatProperty,
+ EnumProperty,
+)
from bpy.app.translations import pgettext_tip as tip_
@@ -130,6 +130,20 @@ def execute_context_assign(self, context):
return operator_path_undo_return(context, data_path)
+def module_filesystem_remove(path_base, module_name):
+ import os
+ module_name = os.path.splitext(module_name)[0]
+ for f in os.listdir(path_base):
+ f_base = os.path.splitext(f)[0]
+ if f_base == module_name:
+ f_full = os.path.join(path_base, f)
+
+ if os.path.isdir(f_full):
+ os.rmdir(f_full)
+ else:
+ os.remove(f_full)
+
+
class BRUSH_OT_active_index_set(Operator):
"""Set active sculpt/paint brush from it's number"""
bl_idname = "brush.active_index_set"
@@ -907,7 +921,10 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
# an operator (common case - just button referencing an op)
if hasattr(bpy.types, class_name.upper() + "_OT_" + class_prop):
if do_url:
- url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
+ url = (
+ "%s/bpy.ops.%s.html#bpy.ops.%s.%s" %
+ (url_prefix, class_name, class_name, class_prop)
+ )
else:
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
else:
@@ -922,7 +939,10 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
class_name, class_prop = class_name.split("_OT_", 1)
class_name = class_name.lower()
if do_url:
- url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" % (url_prefix, class_name, class_name, class_prop))
+ url = (
+ "%s/bpy.ops.%s.html#bpy.ops.%s.%s" %
+ (url_prefix, class_name, class_name, class_prop)
+ )
else:
rna = "bpy.ops.%s.%s" % (class_name, class_prop)
else:
@@ -938,9 +958,12 @@ def _wm_doc_get_id(doc_id, do_url=True, url_prefix=""):
rna_parent = rna_parent.base
if do_url:
- url = ("%s/bpy.types.%s.html#bpy.types.%s.%s" % (url_prefix, class_name, class_name, class_prop))
+ url = (
+ "%s/bpy.types.%s.html#bpy.types.%s.%s" %
+ (url_prefix, class_name, class_name, class_prop)
+ )
else:
- rna = ("bpy.types.%s.%s" % (class_name, class_prop))
+ rna = "bpy.types.%s.%s" % (class_name, class_prop)
else:
# We assume this is custom property, only try to generate generic url/rna_id...
if do_url:
@@ -1008,11 +1031,9 @@ class WM_OT_doc_view(Operator):
doc_id = doc_id
if bpy.app.version_cycle == "release":
- _prefix = ("https://www.blender.org/api/blender_python_api_%s%s_release" %
- ("_".join(str(v) for v in bpy.app.version[:2]), bpy.app.version_char))
+ _prefix = ("https://docs.blender.org/api/blender_python_api_current")
else:
- _prefix = ("https://www.blender.org/api/blender_python_api_%s" %
- "_".join(str(v) for v in bpy.app.version))
+ _prefix = ("https://docs.blender.org/api/blender_python_api_master")
def execute(self, context):
url = _wm_doc_get_id(self.doc_id, do_url=True, url_prefix=self._prefix)
@@ -1089,10 +1110,10 @@ class WM_OT_properties_edit(Operator):
def execute(self, context):
from rna_prop_ui import (
- rna_idprop_ui_prop_get,
- rna_idprop_ui_prop_clear,
- rna_idprop_ui_prop_update,
- )
+ rna_idprop_ui_prop_get,
+ rna_idprop_ui_prop_clear,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
value = self.value
@@ -1269,9 +1290,9 @@ class WM_OT_properties_add(Operator):
def execute(self, context):
from rna_prop_ui import (
- rna_idprop_ui_prop_get,
- rna_idprop_ui_prop_update,
- )
+ rna_idprop_ui_prop_get,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
item = eval("context.%s" % data_path)
@@ -1286,10 +1307,10 @@ class WM_OT_properties_add(Operator):
return prop_new
- prop = unique_name(
- {*item.keys(),
- *type(item).bl_rna.properties.keys(),
- })
+ prop = unique_name({
+ *item.keys(),
+ *type(item).bl_rna.properties.keys(),
+ })
item[prop] = 1.0
rna_idprop_ui_prop_update(item, prop)
@@ -1329,9 +1350,9 @@ class WM_OT_properties_remove(Operator):
def execute(self, context):
from rna_prop_ui import (
- rna_idprop_ui_prop_clear,
- rna_idprop_ui_prop_update,
- )
+ rna_idprop_ui_prop_clear,
+ rna_idprop_ui_prop_update,
+ )
data_path = self.data_path
item = eval("context.%s" % data_path)
prop = self.property
@@ -1369,7 +1390,10 @@ class WM_OT_appconfig_default(Operator):
filepath = os.path.join(bpy.utils.preset_paths("interaction")[0], "blender.py")
if os.path.exists(filepath):
- bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
+ bpy.ops.script.execute_preset(
+ filepath=filepath,
+ menu_idname="USERPREF_MT_interaction_presets",
+ )
return {'FINISHED'}
@@ -1389,7 +1413,10 @@ class WM_OT_appconfig_activate(Operator):
filepath = self.filepath.replace("keyconfig", "interaction")
if os.path.exists(filepath):
- bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
+ bpy.ops.script.execute_preset(
+ filepath=filepath,
+ menu_idname="USERPREF_MT_interaction_presets",
+ )
return {'FINISHED'}
@@ -1494,7 +1521,7 @@ class WM_OT_blenderplayer_start(Operator):
"-g", "show_profile", "=", "%d" % gs.show_framerate_profile,
"-g", "show_properties", "=", "%d" % gs.show_debug_properties,
"-g", "ignore_deprecation_warnings", "=", "%d" % (not gs.use_deprecation_warnings),
- ])
+ ])
# finish the call with the path to the blend file
args.append(filepath)
@@ -1624,10 +1651,11 @@ class WM_OT_keyconfig_export(Operator):
wm = context.window_manager
- keyconfig_utils.keyconfig_export(wm,
- wm.keyconfigs.active,
- self.filepath,
- )
+ keyconfig_utils.keyconfig_export(
+ wm,
+ wm.keyconfigs.active,
+ self.filepath,
+ )
return {'FINISHED'}
@@ -1892,7 +1920,10 @@ class WM_OT_theme_install(Operator):
try:
shutil.copyfile(xmlfile, path_dest)
- bpy.ops.script.execute_preset(filepath=path_dest, menu_idname="USERPREF_MT_interface_theme_presets")
+ bpy.ops.script.execute_preset(
+ filepath=path_dest,
+ menu_idname="USERPREF_MT_interface_theme_presets",
+ )
except:
traceback.print_exc()
@@ -1919,10 +1950,12 @@ class WM_OT_addon_refresh(Operator):
return {'FINISHED'}
+# Note: shares some logic with WM_OT_app_template_install
+# but not enough to de-duplicate. Fixed here may apply to both.
class WM_OT_addon_install(Operator):
"Install an add-on"
bl_idname = "wm.addon_install"
- bl_label = "Install from File..."
+ bl_label = "Install Add-on from File..."
overwrite = BoolProperty(
name="Overwrite",
@@ -1953,20 +1986,6 @@ class WM_OT_addon_install(Operator):
options={'HIDDEN'},
)
- @staticmethod
- def _module_remove(path_addons, module):
- import os
- module = os.path.splitext(module)[0]
- for f in os.listdir(path_addons):
- f_base = os.path.splitext(f)[0]
- if f_base == module:
- f_full = os.path.join(path_addons, f)
-
- if os.path.isdir(f_full):
- os.rmdir(f_full)
- else:
- os.remove(f_full)
-
def execute(self, context):
import addon_utils
import traceback
@@ -2019,7 +2038,7 @@ class WM_OT_addon_install(Operator):
if self.overwrite:
for f in file_to_extract.namelist():
- WM_OT_addon_install._module_remove(path_addons, f)
+ module_filesystem_remove(path_addons, f)
else:
for f in file_to_extract.namelist():
path_dest = os.path.join(path_addons, os.path.basename(f))
@@ -2037,7 +2056,7 @@ class WM_OT_addon_install(Operator):
path_dest = os.path.join(path_addons, os.path.basename(pyfile))
if self.overwrite:
- WM_OT_addon_install._module_remove(path_addons, os.path.basename(pyfile))
+ module_filesystem_remove(path_addons, os.path.basename(pyfile))
elif os.path.exists(path_dest):
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
return {'CANCELLED'}
@@ -2072,7 +2091,10 @@ class WM_OT_addon_install(Operator):
bpy.utils.refresh_script_paths()
# print message
- msg = tip_("Modules Installed from %r into %r (%s)") % (pyfile, path_addons, ", ".join(sorted(addons_new)))
+ msg = (
+ tip_("Modules Installed (%s) from %r into %r") %
+ (", ".join(sorted(addons_new)), pyfile, path_addons)
+ )
print(msg)
self.report({'INFO'}, msg)
@@ -2166,6 +2188,7 @@ class WM_OT_addon_expand(Operator):
return {'FINISHED'}
+
class WM_OT_addon_userpref_show(Operator):
"Show add-on user preferences"
bl_idname = "wm.addon_userpref_show"
@@ -2194,3 +2217,160 @@ class WM_OT_addon_userpref_show(Operator):
bpy.ops.screen.userpref_show('INVOKE_DEFAULT')
return {'FINISHED'}
+
+
+# Note: shares some logic with WM_OT_addon_install
+# but not enough to de-duplicate. Fixes here may apply to both.
+class WM_OT_app_template_install(Operator):
+ "Install an application-template"
+ bl_idname = "wm.app_template_install"
+ bl_label = "Install Template from File..."
+
+ overwrite = BoolProperty(
+ name="Overwrite",
+ description="Remove existing template with the same ID",
+ default=True,
+ )
+
+ filepath = StringProperty(
+ subtype='FILE_PATH',
+ )
+ filter_folder = BoolProperty(
+ name="Filter folders",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_glob = StringProperty(
+ default="*.zip",
+ options={'HIDDEN'},
+ )
+
+ def execute(self, context):
+ import traceback
+ import zipfile
+ import shutil
+ import os
+
+ filepath = self.filepath
+
+ path_app_templates = bpy.utils.user_resource(
+ 'SCRIPTS', os.path.join("startup", "bl_app_templates_user"),
+ create=True,
+ )
+
+ if not path_app_templates:
+ self.report({'ERROR'}, "Failed to get add-ons path")
+ return {'CANCELLED'}
+
+ if not os.path.isdir(path_app_templates):
+ try:
+ os.makedirs(path_app_templates, exist_ok=True)
+ except:
+ traceback.print_exc()
+
+ app_templates_old = set(os.listdir(path_app_templates))
+
+ # check to see if the file is in compressed format (.zip)
+ if zipfile.is_zipfile(filepath):
+ try:
+ file_to_extract = zipfile.ZipFile(filepath, 'r')
+ except:
+ traceback.print_exc()
+ return {'CANCELLED'}
+
+ if self.overwrite:
+ for f in file_to_extract.namelist():
+ module_filesystem_remove(path_app_templates, f)
+ else:
+ for f in file_to_extract.namelist():
+ path_dest = os.path.join(path_app_templates, os.path.basename(f))
+ if os.path.exists(path_dest):
+ self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
+ return {'CANCELLED'}
+
+ try: # extract the file to "bl_app_templates_user"
+ file_to_extract.extractall(path_app_templates)
+ except:
+ traceback.print_exc()
+ return {'CANCELLED'}
+
+ else:
+ # Only support installing zipfiles
+ self.report({'WARNING'}, "Expected a zip-file %r\n" % filepath)
+ return {'CANCELLED'}
+
+ app_templates_new = set(os.listdir(path_app_templates)) - app_templates_old
+
+ # in case a new module path was created to install this addon.
+ bpy.utils.refresh_script_paths()
+
+ # print message
+ msg = (
+ tip_("Template Installed (%s) from %r into %r") %
+ (", ".join(sorted(app_templates_new)), filepath, path_app_templates)
+ )
+ print(msg)
+ self.report({'INFO'}, msg)
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ wm.fileselect_add(self)
+ return {'RUNNING_MODAL'}
+
+
+classes = (
+ BRUSH_OT_active_index_set,
+ WM_OT_addon_disable,
+ WM_OT_addon_enable,
+ WM_OT_addon_expand,
+ WM_OT_addon_install,
+ WM_OT_addon_refresh,
+ WM_OT_addon_remove,
+ WM_OT_addon_userpref_show,
+ WM_OT_app_template_install,
+ WM_OT_appconfig_activate,
+ WM_OT_appconfig_default,
+ WM_OT_blenderplayer_start,
+ WM_OT_context_collection_boolean_set,
+ WM_OT_context_cycle_array,
+ WM_OT_context_cycle_enum,
+ WM_OT_context_cycle_int,
+ WM_OT_context_menu_enum,
+ WM_OT_context_modal_mouse,
+ WM_OT_context_pie_enum,
+ WM_OT_context_scale_float,
+ WM_OT_context_scale_int,
+ WM_OT_context_set_boolean,
+ WM_OT_context_set_enum,
+ WM_OT_context_set_float,
+ WM_OT_context_set_id,
+ WM_OT_context_set_int,
+ WM_OT_context_set_string,
+ WM_OT_context_set_value,
+ WM_OT_context_toggle,
+ WM_OT_context_toggle_enum,
+ WM_OT_copy_prev_settings,
+ WM_OT_doc_view,
+ WM_OT_doc_view_manual,
+ WM_OT_keyconfig_activate,
+ WM_OT_keyconfig_export,
+ WM_OT_keyconfig_import,
+ WM_OT_keyconfig_remove,
+ WM_OT_keyconfig_test,
+ WM_OT_keyitem_add,
+ WM_OT_keyitem_remove,
+ WM_OT_keyitem_restore,
+ WM_OT_keymap_restore,
+ WM_OT_operator_cheat_sheet,
+ WM_OT_operator_pie_enum,
+ WM_OT_path_open,
+ WM_OT_properties_add,
+ WM_OT_properties_context_change,
+ WM_OT_properties_edit,
+ WM_OT_properties_remove,
+ WM_OT_sysinfo,
+ WM_OT_theme_install,
+ WM_OT_url_open,
+)
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 0f26ff75715..c5772101df8 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -23,8 +23,7 @@
# support reloading sub-modules
if "bpy" in locals():
from importlib import reload
- for val in _modules_loaded:
- reload(val)
+ _modules_loaded[:] = [reload(val) for val in _modules_loaded]
del reload
_modules = [
@@ -70,7 +69,6 @@ _modules = [
"space_graph",
"space_image",
"space_info",
- "space_collections",
"space_logic",
"space_nla",
"space_node",
@@ -96,7 +94,10 @@ del _namespace
def register():
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for mod in _modules_loaded:
+ for cls in mod.classes:
+ register_class(cls)
# space_userprefs.py
from bpy.props import StringProperty, EnumProperty
@@ -145,8 +146,11 @@ def register():
def unregister():
- bpy.utils.unregister_module(__name__)
-
+ from bpy.utils import unregister_class
+ for mod in reversed(_modules_loaded):
+ for cls in reversed(mod.classes):
+ if cls.is_registered:
+ unregister_class(cls)
# Define a default UIList, when a list does not need any custom drawing...
# Keep in sync with its #defined name in UI_interface.h
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 046b5eb2aa5..84bae18dd6f 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -139,6 +139,11 @@ class OnionSkinButtonsPanel:
col.label(text="Display:")
col.prop(arm, "show_only_ghost_selected", text="Selected Only")
+
+classes = (
+)
+
if __name__ == "__main__": # only for live edit.
- import bpy
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_collection.py b/release/scripts/startup/bl_ui/properties_collection.py
index 88d78f98ef2..c1e2b00966c 100644
--- a/release/scripts/startup/bl_ui/properties_collection.py
+++ b/release/scripts/startup/bl_ui/properties_collection.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel, UIList
+from bpy.types import Panel
class CollectionButtonsPanel:
@@ -43,86 +43,83 @@ class COLLECTION_PT_context_collection(CollectionButtonsPanel, Panel):
layout.prop(collection, "name", text="", icon='COLLAPSEMENU')
-class COLLECTION_UL_objects(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.Object)
- ob = item
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- layout.label(ob.name, icon_value=icon)
-
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label("", icon_value=icon)
-
+class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
+ bl_label = "Render Settings"
+ COMPAT_ENGINES = {'BLENDER_CLAY'}
-class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
- bl_label = "Objects"
+ @classmethod
+ def poll(cls, context):
+ scene = context.scene
+ return scene and (scene.render.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- scene = context.scene
- collection = context.scene_collection
-
- row = layout.row()
- row.template_list("COLLECTION_UL_objects", "name", collection, "objects", collection.objects, "active_index", rows=2)
-
- col = row.column(align=True)
- col.operator("collections.objects_add", icon='ZOOMIN', text="")
- col.operator("collections.objects_remove", icon='ZOOMOUT', text="")
-
- row = layout.row(align=True)
- row.operator("collections.objects_select", text="Select")
- row.operator("collections.objects_deselect", text="Deselect")
+ scene_props = context.scene.collection_properties['BLENDER_CLAY']
+ collection = context.layer_collection
+ collection_props = collection.engine_overrides['BLENDER_CLAY']
+ col = layout.column()
+ col.template_override_property(collection_props, scene_props, "matcap_icon", custom_template="icon_view")
+ col.template_override_property(collection_props, scene_props, "matcap_rotation")
+ col.template_override_property(collection_props, scene_props, "matcap_hue")
+ col.template_override_property(collection_props, scene_props, "matcap_saturation")
+ col.template_override_property(collection_props, scene_props, "matcap_value")
+ col.template_override_property(collection_props, scene_props, "ssao_factor_cavity")
+ col.template_override_property(collection_props, scene_props, "ssao_factor_edge")
+ col.template_override_property(collection_props, scene_props, "ssao_distance")
+ col.template_override_property(collection_props, scene_props, "ssao_attenuation")
-def template_engine_settings(col, settings, name, use_icon_view=False):
- icons = {
- False: 'ZOOMIN',
- True: 'X',
- }
- use_name = "{0}_use".format(name)
- use = getattr(settings, use_name)
+class COLLECTION_PT_object_mode_settings(CollectionButtonsPanel, Panel):
+ bl_label = "Object Mode Settings"
- row = col.row()
- col = row.column()
- col.active = use
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and (ob.mode == 'OBJECT')
- if use_icon_view:
- col.template_icon_view(settings, name)
- else:
- col.prop(settings, name)
+ def draw(self, context):
+ layout = self.layout
+ scene_props = context.scene.collection_properties['ObjectMode']
+ collection = context.layer_collection
+ collection_props = collection.engine_overrides['ObjectMode']
- row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False)
+ col = layout.column()
+ col.template_override_property(collection_props, scene_props, "show_wire")
+ col.template_override_property(collection_props, scene_props, "show_backface_culling")
-class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
- bl_label = "Render Settings"
- COMPAT_ENGINES = {'BLENDER_CLAY'}
+class COLLECTION_PT_edit_mode_settings(CollectionButtonsPanel, Panel):
+ bl_label = "Edit Mode Settings"
@classmethod
def poll(cls, context):
- scene = context.scene
- return scene and (scene.render.engine in cls.COMPAT_ENGINES)
+ ob = context.object
+ return ob and (ob.mode == 'EDIT')
def draw(self, context):
layout = self.layout
-
+ scene_props = context.scene.collection_properties['EditMode']
collection = context.layer_collection
- settings = collection.get_engine_settings()
+ collection_props = collection.engine_overrides['EditMode']
col = layout.column()
- template_engine_settings(col, settings, "type")
- template_engine_settings(col, settings, "matcap_icon", use_icon_view=True)
- template_engine_settings(col, settings, "matcap_rotation")
- template_engine_settings(col, settings, "matcap_hue")
- template_engine_settings(col, settings, "matcap_saturation")
- template_engine_settings(col, settings, "matcap_value")
- template_engine_settings(col, settings, "ssao_factor_cavity")
- template_engine_settings(col, settings, "ssao_factor_edge")
- template_engine_settings(col, settings, "ssao_distance")
- template_engine_settings(col, settings, "ssao_attenuation")
+ col.template_override_property(collection_props, scene_props, "show_occlude_wire")
+ col.template_override_property(collection_props, scene_props, "backwire_opacity")
+ col.template_override_property(collection_props, scene_props, "face_normals_show")
+ col.template_override_property(collection_props, scene_props, "vert_normals_show")
+ col.template_override_property(collection_props, scene_props, "loop_normals_show")
+ col.template_override_property(collection_props, scene_props, "normals_length")
+
+classes = (
+ COLLECTION_PT_context_collection,
+ COLLECTION_PT_clay_settings,
+ COLLECTION_PT_object_mode_settings,
+ COLLECTION_PT_edit_mode_settings,
+)
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index cb5f1595ff3..00892d5f85b 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -941,5 +941,12 @@ class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
for con in context.pose_bone.constraints:
self.draw_constraint(context, con)
+classes = (
+ OBJECT_PT_constraints,
+ BONE_PT_constraints,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 8261f0c7770..a2ecf984eb5 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -328,5 +328,21 @@ class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.Armature
+
+classes = (
+ DATA_PT_context_arm,
+ DATA_PT_skeleton,
+ DATA_PT_display,
+ DATA_PT_bone_group_specials,
+ DATA_PT_bone_groups,
+ DATA_PT_pose_library,
+ DATA_PT_ghost,
+ DATA_PT_iksolver_itasc,
+ DATA_PT_motion_paths,
+ DATA_PT_custom_props_arm,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 3a5475514c9..132c355ed99 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -449,5 +449,20 @@ class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
else:
return "active_bone"
+
+classes = (
+ BONE_PT_context_bone,
+ BONE_PT_transform,
+ BONE_PT_transform_locks,
+ BONE_PT_curved,
+ BONE_PT_relations,
+ BONE_PT_display,
+ BONE_PT_inverse_kinematics,
+ BONE_PT_deform,
+ BONE_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index c6fa77aec00..edab1c5b22f 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -37,7 +37,7 @@ class CAMERA_MT_presets(Menu):
bl_label = "Camera Presets"
preset_subdir = "camera"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
draw = Menu.draw_preset
@@ -45,14 +45,14 @@ class SAFE_AREAS_MT_presets(Menu):
bl_label = "Camera Presets"
preset_subdir = "safe_areas"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
draw = Menu.draw_preset
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -72,7 +72,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
class DATA_PT_lens(CameraButtonsPanel, Panel):
bl_label = "Lens"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -183,7 +183,7 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Camera"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -217,7 +217,7 @@ class DATA_PT_camera(CameraButtonsPanel, Panel):
class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
bl_label = "Depth of Field"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -247,7 +247,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
bl_label = "Display"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -277,7 +277,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
bl_label = "Safe Areas"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw_header(self, context):
cam = context.camera
@@ -293,7 +293,7 @@ class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
_context_path = "object.data"
_property_type = bpy.types.Camera
@@ -325,5 +325,20 @@ def draw_display_safe_settings(layout, safe_data, settings):
col.prop(safe_data, "action_center", slider=True)
+classes = (
+ CAMERA_MT_presets,
+ SAFE_AREAS_MT_presets,
+ DATA_PT_context_camera,
+ DATA_PT_lens,
+ DATA_PT_camera,
+ DATA_PT_camera_stereoscopy,
+ DATA_PT_camera_dof,
+ DATA_PT_camera_display,
+ DATA_PT_camera_safe_areas,
+ DATA_PT_custom_props_camera,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 33af812b6c4..ac1eb9505a6 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -431,5 +431,21 @@ class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.Curve
+
+classes = (
+ DATA_PT_context_curve,
+ DATA_PT_shape_curve,
+ DATA_PT_curve_texture_space,
+ DATA_PT_geometry_curve,
+ DATA_PT_pathanim,
+ DATA_PT_active_spline,
+ DATA_PT_font,
+ DATA_PT_paragraph,
+ DATA_PT_text_boxes,
+ DATA_PT_custom_props_curve,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index a752d3517de..c66ff87ecbd 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -55,5 +55,12 @@ class DATA_PT_empty(DataButtonsPanel, Panel):
layout.prop(ob, "empty_draw_size", text="Size")
+
+classes = (
+ DATA_PT_empty,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
index 30cd39d2e2f..31ad299f924 100644
--- a/release/scripts/startup/bl_ui/properties_data_lamp.py
+++ b/release/scripts/startup/bl_ui/properties_data_lamp.py
@@ -26,7 +26,7 @@ class LAMP_MT_sunsky_presets(Menu):
bl_label = "Sun & Sky Presets"
preset_subdir = "sunsky"
preset_operator = "script.execute_preset"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
draw = Menu.draw_preset
@@ -44,7 +44,7 @@ class DataButtonsPanel:
class DATA_PT_context_lamp(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -68,7 +68,7 @@ class DATA_PT_context_lamp(DataButtonsPanel, Panel):
class DATA_PT_preview(DataButtonsPanel, Panel):
bl_label = "Preview"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
def draw(self, context):
self.layout.template_preview(context.lamp)
@@ -76,7 +76,7 @@ class DATA_PT_preview(DataButtonsPanel, Panel):
class DATA_PT_lamp(DataButtonsPanel, Panel):
bl_label = "Lamp"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
def draw(self, context):
layout = self.layout
@@ -96,6 +96,7 @@ class DATA_PT_lamp(DataButtonsPanel, Panel):
sub.label(text="Falloff:")
sub.prop(lamp, "falloff_type", text="")
sub.prop(lamp, "distance")
+ sub.prop(lamp, "shadow_soft_size", text="Radius")
if lamp.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
col.label(text="Attenuation Factors:")
@@ -312,7 +313,7 @@ class DATA_PT_shadow(DataButtonsPanel, Panel):
class DATA_PT_area(DataButtonsPanel, Panel):
bl_label = "Area Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -338,7 +339,7 @@ class DATA_PT_area(DataButtonsPanel, Panel):
class DATA_PT_spot(DataButtonsPanel, Panel):
bl_label = "Spot Shape"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -374,7 +375,7 @@ class DATA_PT_spot(DataButtonsPanel, Panel):
class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
bl_label = "Falloff Curve"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
@classmethod
def poll(cls, context):
@@ -390,9 +391,25 @@ class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
_context_path = "object.data"
_property_type = bpy.types.Lamp
+
+classes = (
+ LAMP_MT_sunsky_presets,
+ DATA_PT_context_lamp,
+ DATA_PT_preview,
+ DATA_PT_lamp,
+ DATA_PT_sunsky,
+ DATA_PT_shadow,
+ DATA_PT_area,
+ DATA_PT_spot,
+ DATA_PT_falloff_curve,
+ DATA_PT_custom_props_lamp,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index cbfa6961e8c..4b3fd48c195 100644
--- a/release/scripts/startup/bl_ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -82,5 +82,14 @@ class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.Lattice
+
+classes = (
+ DATA_PT_context_lattice,
+ DATA_PT_lattice,
+ DATA_PT_custom_props_lattice,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 59907692fe0..3e90eacd547 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -24,7 +24,7 @@ from rna_prop_ui import PropertyPanel
class MESH_MT_vertex_group_specials(Menu):
bl_label = "Vertex Group Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -48,7 +48,7 @@ class MESH_MT_vertex_group_specials(Menu):
class MESH_MT_shape_key_specials(Menu):
bl_label = "Shape Key Specials"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -126,7 +126,7 @@ class MeshButtonsPanel:
class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -143,7 +143,7 @@ class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
class DATA_PT_normals(MeshButtonsPanel, Panel):
bl_label = "Normals"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -164,7 +164,7 @@ class DATA_PT_normals(MeshButtonsPanel, Panel):
class DATA_PT_texture_space(MeshButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -183,7 +183,7 @@ class DATA_PT_texture_space(MeshButtonsPanel, Panel):
class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
bl_label = "Vertex Groups"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
@@ -229,7 +229,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
@@ -322,7 +322,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
bl_label = "UV Maps"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -341,7 +341,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -361,7 +361,7 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
class DATA_PT_customdata(MeshButtonsPanel, Panel):
bl_label = "Geometry Data"
bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout
@@ -387,10 +387,29 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
+classes = (
+ MESH_MT_vertex_group_specials,
+ MESH_MT_shape_key_specials,
+ MESH_UL_vgroups,
+ MESH_UL_shape_keys,
+ MESH_UL_uvmaps_vcols,
+ DATA_PT_context_mesh,
+ DATA_PT_normals,
+ DATA_PT_texture_space,
+ DATA_PT_vertex_groups,
+ DATA_PT_shape_keys,
+ DATA_PT_uv_texture,
+ DATA_PT_vertex_colors,
+ DATA_PT_customdata,
+ DATA_PT_custom_props_mesh,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index b42258c386a..a621dc7210f 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -135,5 +135,16 @@ class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.MetaBall
+
+classes = (
+ DATA_PT_context_metaball,
+ DATA_PT_metaball,
+ DATA_PT_mball_texture_space,
+ DATA_PT_metaball_element,
+ DATA_PT_custom_props_metaball,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index d66fb08bcd6..a37d61dd0af 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -569,6 +569,14 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_mirror_u", text="U")
col.prop(md, "use_mirror_v", text="V")
+ col = layout.column(align=True)
+
+ if md.use_mirror_u:
+ col.prop(md, "mirror_offset_u")
+
+ if md.use_mirror_v:
+ col.prop(md, "mirror_offset_v")
+
col = layout.column()
if md.use_mirror_merge is True:
@@ -951,6 +959,23 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def SURFACE(self, layout, ob, md):
layout.label(text="Settings are inside the Physics tab")
+ def SURFACE_DEFORM(self, layout, ob, md):
+ col = layout.column()
+ col.active = not md.is_bound
+
+ col.prop(md, "target")
+ col.prop(md, "falloff")
+
+ layout.separator()
+
+ col = layout.column()
+ col.active = md.target is not None
+
+ if md.is_bound:
+ col.operator("object.surfacedeform_bind", text="Unbind")
+ else:
+ col.operator("object.surfacedeform_bind", text="Bind")
+
def UV_PROJECT(self, layout, ob, md):
split = layout.split()
@@ -1320,7 +1345,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
row.prop(md, "thickness_vertex_group", text="Factor")
col.prop(md, "use_crease", text="Crease Edges")
- col.prop(md, "crease_weight", text="Crease Weight")
+ row = col.row()
+ row.active = md.use_crease
+ row.prop(md, "crease_weight", text="Crease Weight")
col = split.column()
@@ -1503,5 +1530,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
+classes = (
+ DATA_PT_modifiers,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py
index 5ed0f8c3265..eecb2690302 100644
--- a/release/scripts/startup/bl_ui/properties_data_speaker.py
+++ b/release/scripts/startup/bl_ui/properties_data_speaker.py
@@ -121,5 +121,16 @@ class DATA_PT_custom_props_speaker(DataButtonsPanel, PropertyPanel, Panel):
_context_path = "object.data"
_property_type = bpy.types.Speaker
+
+classes = (
+ DATA_PT_context_speaker,
+ DATA_PT_speaker,
+ DATA_PT_distance,
+ DATA_PT_cone,
+ DATA_PT_custom_props_speaker,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index e0620447185..9c5be7624e0 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -828,5 +828,17 @@ class MATERIAL_PT_freestyle_line(MaterialFreestyleButtonsPanel, Panel):
row.prop(mat, "line_priority", text="Priority")
+classes = (
+ RENDER_PT_freestyle,
+ RENDERLAYER_UL_linesets,
+ RENDER_MT_lineset_specials,
+ RENDERLAYER_PT_freestyle,
+ RENDERLAYER_PT_freestyle_lineset,
+ RENDERLAYER_PT_freestyle_linestyle,
+ MATERIAL_PT_freestyle_line,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index ec061370fe5..46b34373aa5 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -852,5 +852,30 @@ class OBJECT_PT_levels_of_detail(ObjectButtonsPanel, Panel):
row.menu("OBJECT_MT_lod_tools", text="", icon='TRIA_DOWN')
+classes = (
+ PHYSICS_PT_game_physics,
+ PHYSICS_PT_game_collision_bounds,
+ PHYSICS_PT_game_obstacles,
+ RENDER_PT_embedded,
+ RENDER_PT_game_player,
+ RENDER_PT_game_stereo,
+ RENDER_PT_game_shading,
+ RENDER_PT_game_system,
+ RENDER_PT_game_display,
+ SCENE_PT_game_physics,
+ SCENE_PT_game_physics_obstacles,
+ SCENE_PT_game_navmesh,
+ SCENE_PT_game_hysteresis,
+ WORLD_PT_game_context_world,
+ WORLD_PT_game_world,
+ WORLD_PT_game_environment_lighting,
+ WORLD_PT_game_mist,
+ DATA_PT_shadow_game,
+ OBJECT_MT_lod_tools,
+ OBJECT_PT_levels_of_detail,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
index 4529c127839..42e8d5272b3 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -1155,3 +1155,24 @@ class GreasePencilToolsPanel:
layout.separator()
gpencil_stroke_placement_settings(context, layout)
+
+
+classes = (
+ GPENCIL_PIE_tool_palette,
+ GPENCIL_PIE_settings_palette,
+ GPENCIL_PIE_tools_more,
+ GPENCIL_PIE_sculpt,
+ GPENCIL_MT_snap,
+ GPENCIL_MT_gpencil_edit_specials,
+ GPENCIL_UL_brush,
+ GPENCIL_UL_palettecolor,
+ GPENCIL_UL_layer,
+ GPENCIL_MT_layer_specials,
+ GPENCIL_MT_brush_specials,
+ GPENCIL_MT_palettecolor_specials,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index f4836da50bc..a7a67130f2f 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -392,5 +392,17 @@ class MASK_MT_select(Menu):
layout.operator("mask.select_all", text="Inverse").action = 'INVERT'
layout.operator("mask.select_linked", text="Select Linked")
+
+classes = (
+ MASK_UL_layers,
+ MASK_MT_mask,
+ MASK_MT_visibility,
+ MASK_MT_transform,
+ MASK_MT_animation,
+ MASK_MT_select,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index d916007ea41..06ae1847d06 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -71,6 +71,7 @@ class MATERIAL_MT_specials(Menu):
class MATERIAL_UL_matslots(UIList):
+
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.MaterialSlot)
# ob = data
@@ -1052,5 +1053,38 @@ class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
_context_path = "material"
_property_type = bpy.types.Material
+
+classes = (
+ MATERIAL_MT_sss_presets,
+ MATERIAL_MT_specials,
+ MATERIAL_UL_matslots,
+ MATERIAL_PT_context_material,
+ MATERIAL_PT_preview,
+ MATERIAL_PT_pipeline,
+ MATERIAL_PT_diffuse,
+ MATERIAL_PT_specular,
+ MATERIAL_PT_shading,
+ MATERIAL_PT_transp,
+ MATERIAL_PT_mirror,
+ MATERIAL_PT_sss,
+ MATERIAL_PT_halo,
+ MATERIAL_PT_flare,
+ MATERIAL_PT_game_settings,
+ MATERIAL_PT_physics,
+ MATERIAL_PT_strand,
+ MATERIAL_PT_options,
+ MATERIAL_PT_shadow,
+ MATERIAL_PT_transp_game,
+ MATERIAL_PT_volume_density,
+ MATERIAL_PT_volume_shading,
+ MATERIAL_PT_volume_lighting,
+ MATERIAL_PT_volume_transp,
+ MATERIAL_PT_volume_integration,
+ MATERIAL_PT_volume_options,
+ MATERIAL_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 3ff7a248c60..d7e18f81232 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -152,6 +152,33 @@ class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
sub.active = (parent is not None)
+class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
+ bl_label = "Relations Extras"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+
+ split = layout.split()
+
+ if context.scene.render.engine != 'BLENDER_GAME':
+ col = split.column()
+ col.label(text="Tracking Axes:")
+ col.prop(ob, "track_axis", text="Axis")
+ col.prop(ob, "up_axis", text="Up Axis")
+
+ col = split.column()
+ col.prop(ob, "use_slow_parent")
+ row = col.row()
+ row.active = ((ob.parent is not None) and (ob.use_slow_parent))
+ row.prop(ob, "slow_parent_offset", text="Offset")
+
+ layout.prop(ob, "use_extra_recalc_object")
+ layout.prop(ob, "use_extra_recalc_data")
+
+
class GROUP_MT_specials(Menu):
bl_label = "Group Specials"
@@ -296,33 +323,6 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
layout.prop(ob, "dupli_group", text="Group")
-class OBJECT_PT_relations_extras(ObjectButtonsPanel, Panel):
- bl_label = "Relations Extras"
- bl_options = {'DEFAULT_CLOSED'}
-
- def draw(self, context):
- layout = self.layout
-
- ob = context.object
-
- split = layout.split()
-
- if context.scene.render.engine != 'BLENDER_GAME':
- col = split.column()
- col.label(text="Tracking Axes:")
- col.prop(ob, "track_axis", text="Axis")
- col.prop(ob, "up_axis", text="Up Axis")
-
- col = split.column()
- col.prop(ob, "use_slow_parent")
- row = col.row()
- row.active = ((ob.parent is not None) and (ob.use_slow_parent))
- row.prop(ob, "slow_parent_offset", text="Offset")
-
- layout.prop(ob, "use_extra_recalc_object")
- layout.prop(ob, "use_extra_recalc_data")
-
-
from bl_ui.properties_animviz import (
MotionPathButtonsPanel,
OnionSkinButtonsPanel,
@@ -366,5 +366,23 @@ class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
_context_path = "object"
_property_type = bpy.types.Object
+
+classes = (
+ OBJECT_PT_context_object,
+ OBJECT_PT_transform,
+ OBJECT_PT_delta_transform,
+ OBJECT_PT_transform_locks,
+ OBJECT_PT_relations,
+ OBJECT_PT_relations_extras,
+ GROUP_MT_specials,
+ OBJECT_PT_groups,
+ OBJECT_PT_display,
+ OBJECT_PT_duplication,
+ OBJECT_PT_motion_paths,
+ OBJECT_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 09a3a19cbce..dfd20d90ec4 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -309,3 +309,13 @@ def brush_mask_texture_settings(layout, brush):
split = layout.split()
split.prop(mask_tex_slot, "offset")
split.prop(mask_tex_slot, "scale")
+
+
+classes = (
+ VIEW3D_MT_tools_projectpaint_clone,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 29fc56c3fad..2c27c68ed9d 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -23,11 +23,11 @@ from rna_prop_ui import PropertyPanel
from bpy.app.translations import pgettext_iface as iface_
from bl_ui.properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
- basic_force_field_settings_ui,
- basic_force_field_falloff_ui,
- )
+ point_cache_ui,
+ effector_weights_ui,
+ basic_force_field_settings_ui,
+ basic_force_field_falloff_ui,
+)
def particle_panel_enabled(context, psys):
@@ -108,6 +108,7 @@ def find_modifier(ob, psys):
class PARTICLE_UL_particle_systems(bpy.types.UIList):
+
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
ob = data
psys = item
@@ -117,8 +118,10 @@ class PARTICLE_UL_particle_systems(bpy.types.UIList):
layout.prop(psys, "name", text="", emboss=False, icon_value=icon)
if md:
- layout.prop(md, "show_render", emboss=False, icon_only=True, icon='RESTRICT_RENDER_OFF' if md.show_render else 'RESTRICT_RENDER_ON')
- layout.prop(md, "show_viewport", emboss=False, icon_only=True, icon='RESTRICT_VIEW_OFF' if md.show_viewport else 'RESTRICT_VIEW_ON')
+ layout.prop(md, "show_render", emboss=False, icon_only=True,
+ icon='RESTRICT_RENDER_OFF' if md.show_render else 'RESTRICT_RENDER_ON')
+ layout.prop(md, "show_viewport", emboss=False, icon_only=True,
+ icon='RESTRICT_VIEW_OFF' if md.show_viewport else 'RESTRICT_VIEW_ON')
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
@@ -401,7 +404,8 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
label = "ERROR"
icon = 'ERROR'
box.label(label, icon=icon)
- box.label("Iterations: %d .. %d (avg. %d)" % (result.min_iterations, result.max_iterations, result.avg_iterations))
+ box.label("Iterations: %d .. %d (avg. %d)" %
+ (result.min_iterations, result.max_iterations, result.avg_iterations))
box.label("Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error))
@@ -423,7 +427,12 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
phystype = psys.settings.physics_type
if phystype == 'NO' or phystype == 'KEYED':
return False
- return (psys.settings.type in {'EMITTER', 'REACTOR'} or (psys.settings.type == 'HAIR' and (psys.use_hair_dynamics or psys.point_cache.is_baked))) and engine in cls.COMPAT_ENGINES
+ return (
+ (psys.settings.type in {'EMITTER', 'REACTOR'} or
+ (psys.settings.type == 'HAIR' and
+ (psys.use_hair_dynamics or psys.point_cache.is_baked))) and
+ engine in cls.COMPAT_ENGINES
+ )
def draw(self, context):
psys = context.particle_system
@@ -743,7 +752,8 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
layout.label(text="Fluid interaction:")
row = layout.row()
- row.template_list("UI_UL_list", "particle_targets", psys, "targets", psys, "active_particle_target_index", rows=4)
+ row.template_list("UI_UL_list", "particle_targets", psys, "targets",
+ psys, "active_particle_target_index", rows=4)
col = row.column()
sub = col.row()
@@ -760,7 +770,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
row = layout.row()
if part.physics_type == 'KEYED':
col = row.column()
- #doesn't work yet
+ # doesn't work yet
#col.alert = key.valid
col.prop(key, "object", text="")
col.prop(key, "system", text="System")
@@ -770,7 +780,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
col.prop(key, "duration")
elif part.physics_type == 'BOIDS':
sub = row.row()
- #doesn't work yet
+ # doesn't work yet
#sub.alert = key.valid
sub.prop(key, "object", text="")
sub.prop(key, "system", text="System")
@@ -778,7 +788,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
layout.prop(key, "alliance", expand=True)
elif part.physics_type == 'FLUID':
sub = row.row()
- #doesn't work yet
+ # doesn't work yet
#sub.alert = key.valid
sub.prop(key, "object", text="")
sub.prop(key, "system", text="System")
@@ -831,7 +841,8 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
row.label(text="")
row = layout.row()
- row.template_list("UI_UL_list", "particle_boids_rules", state, "rules", state, "active_boid_rule_index", rows=4)
+ row.template_list("UI_UL_list", "particle_boids_rules", state,
+ "rules", state, "active_boid_rule_index", rows=4)
col = row.column()
sub = col.row()
@@ -848,7 +859,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
if rule:
row = layout.row()
row.prop(rule, "name", text="")
- #somebody make nice icons for boids here please! -jahka
+ # somebody make nice icons for boids here please! -jahka
row.prop(rule, "use_in_air", icon='TRIA_UP', text="")
row.prop(rule, "use_on_land", icon='TRIA_DOWN', text="")
@@ -1404,5 +1415,29 @@ class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings
+
+classes = (
+ PARTICLE_MT_specials,
+ PARTICLE_MT_hair_dynamics_presets,
+ PARTICLE_UL_particle_systems,
+ PARTICLE_PT_context_particles,
+ PARTICLE_PT_emission,
+ PARTICLE_PT_hair_dynamics,
+ PARTICLE_PT_cache,
+ PARTICLE_PT_velocity,
+ PARTICLE_PT_rotation,
+ PARTICLE_PT_physics,
+ PARTICLE_PT_boidbrain,
+ PARTICLE_PT_render,
+ PARTICLE_PT_draw,
+ PARTICLE_PT_children,
+ PARTICLE_PT_field_weights,
+ PARTICLE_PT_force_fields,
+ PARTICLE_PT_vertexgroups,
+ PARTICLE_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 54581c9276d..6ada3c59942 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -258,5 +258,17 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
cloth = context.cloth.settings
effector_weights_ui(self, context, cloth.effector_weights, 'CLOTH')
+classes = (
+ CLOTH_MT_presets,
+ PHYSICS_PT_cloth,
+ PHYSICS_PT_cloth_cache,
+ PHYSICS_PT_cloth_collision,
+ PHYSICS_PT_cloth_stiffness,
+ PHYSICS_PT_cloth_sewing,
+ PHYSICS_PT_cloth_field_weights,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 277b59d187d..0b98d8738dc 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -274,6 +274,8 @@ def basic_force_field_settings_ui(self, context, field):
col.prop(field, "use_global_coords", text="Global")
elif field.type == 'HARMONIC':
col.prop(field, "use_multiple_springs")
+ if field.type == 'FORCE':
+ col.prop(field, "use_gravity_falloff", text="Gravitation")
split = layout.split()
@@ -316,5 +318,12 @@ def basic_force_field_falloff_ui(self, context, field):
sub.active = field.use_max_distance
sub.prop(field, "distance_max", text="Maximum")
+
+classes = (
+ PHYSICS_PT_add,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 6c3a3246cf6..c813350be08 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -529,12 +529,20 @@ class PHYSICS_PT_dp_brush_wave(PhysicButtonsPanel, Panel):
row.prop(brush, "wave_clamp")
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.register_module(__name__)
-
-if __name__ == "__main__":
- register()
+classes = (
+ PHYSICS_UL_dynapaint_surfaces,
+ PHYSICS_PT_dynamic_paint,
+ PHYSICS_PT_dp_advanced_canvas,
+ PHYSICS_PT_dp_canvas_output,
+ PHYSICS_PT_dp_canvas_initial_color,
+ PHYSICS_PT_dp_effects,
+ PHYSICS_PT_dp_cache,
+ PHYSICS_PT_dp_brush_source,
+ PHYSICS_PT_dp_brush_velocity,
+ PHYSICS_PT_dp_brush_wave,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 1cebc0496b0..2b12fcf982d 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -228,5 +228,13 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
col.label(text="Force Fields:")
col.prop(settings, "absorption", text="Absorption")
+
+classes = (
+ PHYSICS_PT_field,
+ PHYSICS_PT_collision,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 5d7034c2e68..ab92370f9ae 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -308,5 +308,16 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
row.prop(fluid, "tracer_particles", text="Tracer")
row.prop(fluid, "generate_particles", text="Generate")
+
+classes = (
+ FLUID_MT_presets,
+ PHYSICS_PT_fluid,
+ PHYSICS_PT_domain_gravity,
+ PHYSICS_PT_domain_boundary,
+ PHYSICS_PT_domain_particles,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index eeb21c046bf..6afdd800b88 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -137,5 +137,14 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
col.prop(rbo, "linear_damping", text="Translation")
col.prop(rbo, "angular_damping", text="Rotation")
+
+classes = (
+ PHYSICS_PT_rigid_body,
+ PHYSICS_PT_rigid_body_collisions,
+ PHYSICS_PT_rigid_body_dynamics,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
index 9d4f51b256b..84a4cbb4b68 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody_constraint.py
@@ -260,5 +260,11 @@ class PHYSICS_PT_rigid_body_constraint(PHYSICS_PT_rigidbody_constraint_panel, Pa
sub.prop(rbc, "spring_damping_ang_z", text="Damping")
+classes = (
+ PHYSICS_PT_rigid_body_constraint,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index ee9135b9dbf..f2e6c1e22e3 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -21,9 +21,9 @@ import bpy
from bpy.types import Panel
from bl_ui.properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
- )
+ point_cache_ui,
+ effector_weights_ui,
+)
class PhysicButtonsPanel:
@@ -380,23 +380,23 @@ class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel):
do_axis_slicing = (slice_method == 'AXIS_ALIGNED')
do_full_slicing = (axis_slice_method == 'FULL')
- row = layout.row();
+ row = layout.row()
row.enabled = do_axis_slicing
row.prop(domain, "axis_slice_method")
- col = layout.column();
+ col = layout.column()
col.enabled = not do_full_slicing and do_axis_slicing
col.prop(domain, "slice_axis")
col.prop(domain, "slice_depth")
- row = layout.row();
+ row = layout.row()
row.enabled = do_full_slicing or not do_axis_slicing
row.prop(domain, "slice_per_voxel")
layout.separator()
layout.label(text="Debug:")
layout.prop(domain, "draw_velocity")
- col = layout.column();
+ col = layout.column()
col.enabled = domain.draw_velocity
col.prop(domain, "vector_draw_type")
col.prop(domain, "vector_scale")
@@ -404,11 +404,25 @@ class PHYSICS_PT_smoke_display_settings(PhysicButtonsPanel, Panel):
layout.separator()
layout.label(text="Color Mapping:")
layout.prop(domain, "use_color_ramp")
- col = layout.column();
+ col = layout.column()
col.enabled = domain.use_color_ramp
col.prop(domain, "coba_field")
col.template_color_ramp(domain, "color_ramp", expand=True)
+classes = (
+ PHYSICS_PT_smoke,
+ PHYSICS_PT_smoke_flow_advanced,
+ PHYSICS_PT_smoke_fire,
+ PHYSICS_PT_smoke_adaptive_domain,
+ PHYSICS_PT_smoke_highres,
+ PHYSICS_PT_smoke_groups,
+ PHYSICS_PT_smoke_cache,
+ PHYSICS_PT_smoke_field_weights,
+ PHYSICS_PT_smoke_display_settings,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index a458af739f2..5960428e4ae 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -244,5 +244,18 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
effector_weights_ui(self, context, softbody.effector_weights, 'SOFTBODY')
+
+classes = (
+ PHYSICS_PT_softbody,
+ PHYSICS_PT_softbody_cache,
+ PHYSICS_PT_softbody_goal,
+ PHYSICS_PT_softbody_edge,
+ PHYSICS_PT_softbody_collision,
+ PHYSICS_PT_softbody_solver,
+ PHYSICS_PT_softbody_field_weights,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 90d46a6ee47..be7104163fd 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -584,24 +584,45 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
sub.prop(rd, "bake_user_scale", text="User Scale")
-class RENDER_PT_clay(RenderButtonsPanel, Panel):
- bl_label = "Default Clay"
+class RENDER_PT_clay_collection_settings(RenderButtonsPanel, Panel):
+ bl_label = "Clay Collection Settings"
COMPAT_ENGINES = {'BLENDER_CLAY'}
def draw(self, context):
- layout = self.layout;
- settings = context.scene.active_engine_settings
- layout.template_icon_view(settings, "matcap_icon")
- layout.prop(settings, "matcap_rotation")
- layout.prop(settings, "matcap_hue")
- layout.prop(settings, "matcap_saturation")
- layout.prop(settings, "matcap_value")
- layout.prop(settings, "ssao_factor_cavity")
- layout.prop(settings, "ssao_factor_edge")
- layout.prop(settings, "ssao_distance")
- layout.prop(settings, "ssao_attenuation")
- layout.prop(settings, "ssao_samples")
+ layout = self.layout
+ props = context.scene.collection_properties['BLENDER_CLAY']
+ col = layout.column()
+ col.template_icon_view(props, "matcap_icon")
+ col.prop(props, "matcap_rotation")
+ col.prop(props, "matcap_hue")
+ col.prop(props, "matcap_saturation")
+ col.prop(props, "matcap_value")
+ col.prop(props, "ssao_factor_cavity")
+ col.prop(props, "ssao_factor_edge")
+ col.prop(props, "ssao_distance")
+ col.prop(props, "ssao_attenuation")
+
+
+classes = (
+ RENDER_MT_presets,
+ RENDER_MT_ffmpeg_presets,
+ RENDER_MT_framerate_presets,
+ RENDER_PT_render,
+ RENDER_PT_dimensions,
+ RENDER_PT_antialiasing,
+ RENDER_PT_motion_blur,
+ RENDER_PT_shading,
+ RENDER_PT_performance,
+ RENDER_PT_post_processing,
+ RENDER_PT_stamp,
+ RENDER_PT_output,
+ RENDER_PT_encoding,
+ RENDER_PT_bake,
+ RENDER_PT_clay_collection_settings,
+)
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index 2545eadc792..d6905cd1975 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -130,5 +130,14 @@ class RENDERLAYER_PT_views(RenderLayerButtonsPanel, Panel):
row.prop(rv, "camera_suffix", text="")
+classes = (
+ RENDERLAYER_UL_renderlayers,
+ RENDERLAYER_PT_layers,
+ RENDERLAYER_UL_renderviews,
+ RENDERLAYER_PT_views,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index d6253ec7fbc..fb93c0b56f2 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -443,5 +443,25 @@ class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
_context_path = "scene"
_property_type = bpy.types.Scene
+
+classes = (
+ SCENE_MT_units_length_presets,
+ SCENE_UL_keying_set_paths,
+ SCENE_PT_scene,
+ SCENE_PT_unit,
+ SCENE_PT_keying_sets,
+ SCENE_PT_keying_set_paths,
+ SCENE_PT_color_management,
+ SCENE_PT_audio,
+ SCENE_PT_physics,
+ SCENE_PT_rigid_body_world,
+ SCENE_PT_rigid_body_cache,
+ SCENE_PT_rigid_body_field_weights,
+ SCENE_PT_simplify,
+ SCENE_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index caf19a9e469..d05527b7ef6 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -21,15 +21,15 @@ import bpy
from bpy.types import Menu, Panel, UIList
from bpy.types import (
- Brush,
- FreestyleLineStyle,
- Lamp,
- Material,
- Object,
- ParticleSettings,
- Texture,
- World,
- )
+ Brush,
+ FreestyleLineStyle,
+ Lamp,
+ Material,
+ Object,
+ ParticleSettings,
+ Texture,
+ World,
+)
from rna_prop_ui import PropertyPanel
@@ -60,6 +60,7 @@ class TEXTURE_MT_envmap_specials(Menu):
class TEXTURE_UL_texslots(UIList):
+
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# assert(isinstance(item, bpy.types.MaterialTextureSlot)
ma = data
@@ -198,7 +199,8 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
if tex_collection:
row = layout.row()
- row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots", idblock, "active_texture_index", rows=2)
+ row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots",
+ idblock, "active_texture_index", rows=2)
col = row.column(align=True)
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
@@ -1210,12 +1212,22 @@ class TEXTURE_PT_influence(TextureSlotPanel, Panel):
row = layout.row()
sub = row.row()
- sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and (tex.texture.use_normal_map or tex.texture.use_derivative_map))
+ sub.active = (
+ (tex.use_map_normal or tex.use_map_warp) and
+ not (tex.texture.type == 'IMAGE' and
+ (tex.texture.use_normal_map or tex.texture.use_derivative_map))
+ )
sub.prop(tex, "bump_method", text="Method")
- # the space setting is supported for: derivative-maps + bump-maps (DEFAULT,BEST_QUALITY), not for normal-maps
+ # the space setting is supported for: derivative-maps + bump-maps
+ # (DEFAULT,BEST_QUALITY), not for normal-maps
sub = row.row()
- sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_LOW_QUALITY', 'BUMP_MEDIUM_QUALITY', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
+ sub.active = (
+ (tex.use_map_normal or tex.use_map_warp) and
+ not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and
+ ((tex.bump_method in {'BUMP_LOW_QUALITY', 'BUMP_MEDIUM_QUALITY', 'BUMP_BEST_QUALITY'}) or
+ (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
+ )
sub.prop(tex, "bump_objectspace", text="Space")
@@ -1224,5 +1236,38 @@ class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
_context_path = "texture"
_property_type = Texture
+
+classes = (
+ TEXTURE_MT_specials,
+ TEXTURE_MT_envmap_specials,
+ TEXTURE_UL_texslots,
+ TEXTURE_PT_context_texture,
+ TEXTURE_PT_preview,
+ TEXTURE_PT_colors,
+ TEXTURE_PT_clouds,
+ TEXTURE_PT_wood,
+ TEXTURE_PT_marble,
+ TEXTURE_PT_magic,
+ TEXTURE_PT_blend,
+ TEXTURE_PT_stucci,
+ TEXTURE_PT_image,
+ TEXTURE_PT_image_sampling,
+ TEXTURE_PT_image_mapping,
+ TEXTURE_PT_envmap,
+ TEXTURE_PT_envmap_sampling,
+ TEXTURE_PT_musgrave,
+ TEXTURE_PT_voronoi,
+ TEXTURE_PT_distortednoise,
+ TEXTURE_PT_voxeldata,
+ TEXTURE_PT_pointdensity,
+ TEXTURE_PT_pointdensity_turbulence,
+ TEXTURE_PT_ocean,
+ TEXTURE_PT_mapping,
+ TEXTURE_PT_influence,
+ TEXTURE_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index e07349a99ee..6aa39580d34 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -248,5 +248,20 @@ class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
_context_path = "world"
_property_type = bpy.types.World
+
+classes = (
+ WORLD_PT_context_world,
+ WORLD_PT_preview,
+ WORLD_PT_world,
+ WORLD_PT_ambient_occlusion,
+ WORLD_PT_environment_lighting,
+ WORLD_PT_indirect_lighting,
+ WORLD_PT_gather,
+ WORLD_PT_mist,
+ WORLD_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 5cc135392c1..3f05620fcf6 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1486,5 +1486,69 @@ class CLIP_MT_stabilize_2d_rotation_specials(Menu):
layout.operator("clip.stabilize_2d_rotation_select")
+classes = (
+ CLIP_UL_tracking_objects,
+ CLIP_HT_header,
+ CLIP_MT_track,
+ CLIP_MT_tracking_editor_menus,
+ CLIP_MT_masking_editor_menus,
+ CLIP_PT_track,
+ CLIP_PT_tools_clip,
+ CLIP_PT_tools_marker,
+ CLIP_PT_tracking_settings,
+ CLIP_PT_tools_tracking,
+ CLIP_PT_tools_plane_tracking,
+ CLIP_PT_tools_solve,
+ CLIP_PT_tools_cleanup,
+ CLIP_PT_tools_geometry,
+ CLIP_PT_tools_orientation,
+ CLIP_PT_tools_object,
+ CLIP_PT_objects,
+ CLIP_PT_plane_track,
+ CLIP_PT_track_settings,
+ CLIP_PT_tracking_camera,
+ CLIP_PT_tracking_lens,
+ CLIP_PT_display,
+ CLIP_PT_marker,
+ CLIP_PT_marker_display,
+ CLIP_PT_stabilization,
+ CLIP_PT_proxy,
+ CLIP_PT_mask,
+ CLIP_PT_mask_layers,
+ CLIP_PT_mask_display,
+ CLIP_PT_active_mask_spline,
+ CLIP_PT_active_mask_point,
+ CLIP_PT_tools_mask,
+ CLIP_PT_tools_mask_add,
+ CLIP_PT_tools_mask_transforms,
+ CLIP_PT_footage,
+ CLIP_PT_footage_info,
+ CLIP_PT_tools_scenesetup,
+ CLIP_PT_grease_pencil,
+ CLIP_PT_grease_pencil_palettecolor,
+ CLIP_PT_tools_grease_pencil_draw,
+ CLIP_PT_tools_grease_pencil_edit,
+ CLIP_PT_tools_grease_pencil_sculpt,
+ CLIP_PT_tools_grease_pencil_brush,
+ CLIP_PT_tools_grease_pencil_brushcurves,
+ CLIP_MT_view,
+ CLIP_MT_clip,
+ CLIP_MT_proxy,
+ CLIP_MT_reconstruction,
+ CLIP_MT_track_visibility,
+ CLIP_MT_track_transform,
+ CLIP_MT_select,
+ CLIP_MT_select_grouped,
+ CLIP_MT_tracking_specials,
+ CLIP_MT_camera_presets,
+ CLIP_MT_track_color_presets,
+ CLIP_MT_tracking_settings_presets,
+ CLIP_MT_track_color_specials,
+ CLIP_MT_stabilize_2d_specials,
+ CLIP_MT_stabilize_2d_rotation_specials,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_collections.py b/release/scripts/startup/bl_ui/space_collections.py
deleted file mode 100644
index 9b612ce2ecd..00000000000
--- a/release/scripts/startup/bl_ui/space_collections.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# ##### BEGIN GPL LICENSE BLOCK #####
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ##### END GPL LICENSE BLOCK #####
-
-# <pep8 compliant>
-import bpy
-from bpy.types import Header, Menu
-
-
-class COLLECTIONS_HT_header(Header):
- bl_space_type = 'COLLECTION_MANAGER'
-
- def draw(self, context):
- layout = self.layout
-
- layout.template_header()
-
- row = layout.row(align=True)
- row.operator("collections.collection_new", text="", icon='NEW')
- row.operator("collections.override_new", text="", icon='LINK_AREA')
- row.operator("collections.collection_link", text="", icon='LINKED')
- row.operator("collections.collection_unlink", text="", icon='UNLINKED')
- row.operator("collections.delete", text="", icon='X')
-
-
-if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index 4266abc5ad7..e6f96d989c7 100644
--- a/release/scripts/startup/bl_ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -102,5 +102,15 @@ def add_scrollback(text, text_type):
bpy.ops.console.scrollback_append(text=l.expandtabs(4),
type=text_type)
+
+classes = (
+ CONSOLE_HT_header,
+ CONSOLE_MT_editor_menus,
+ CONSOLE_MT_console,
+ CONSOLE_MT_language,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 4d365c8dc08..e02649219dd 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -449,5 +449,21 @@ class DOPESHEET_MT_delete(Menu):
layout.operator("action.clean", text="Clean Channels").channels = True
+classes = (
+ DOPESHEET_HT_header,
+ DOPESHEET_MT_editor_menus,
+ DOPESHEET_MT_view,
+ DOPESHEET_MT_select,
+ DOPESHEET_MT_marker,
+ DOPESHEET_MT_channel,
+ DOPESHEET_MT_key,
+ DOPESHEET_MT_key_transform,
+ DOPESHEET_MT_gpencil_channel,
+ DOPESHEET_MT_gpencil_frame,
+ DOPESHEET_MT_delete,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index d7b93dc36f0..bd72dfa9370 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -247,5 +247,18 @@ class FILEBROWSER_PT_advanced_filter(Panel):
col.prop(params, "filter_id")
+classes = (
+ FILEBROWSER_HT_header,
+ FILEBROWSER_UL_dir,
+ FILEBROWSER_PT_system_folders,
+ FILEBROWSER_PT_system_bookmarks,
+ FILEBROWSER_MT_bookmarks_specials,
+ FILEBROWSER_PT_bookmarks,
+ FILEBROWSER_PT_recent_folders,
+ FILEBROWSER_PT_advanced_filter,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 446df9e6e79..21b49df61ae 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -42,10 +42,11 @@ class GRAPH_HT_header(Header):
dopesheet_filter(layout, context)
- layout.prop(st, "use_normalization", text="Normalize")
- row = layout.row()
- row.active = st.use_normalization
- row.prop(st, "use_auto_normalization", text="Auto")
+ row = layout.row(align=True)
+ row.prop(st, "use_normalization", icon='NORMALIZE_FCURVES', text="Normalize", toggle=True)
+ sub = row.row(align=True)
+ sub.active = st.use_normalization
+ sub.prop(st, "use_auto_normalization", icon='FILE_REFRESH', text="", toggle=True)
row = layout.row(align=True)
@@ -298,6 +299,19 @@ class GRAPH_MT_delete(Menu):
layout.operator("graph.clean").channels = False
layout.operator("graph.clean", text="Clean Channels").channels = True
+classes = (
+ GRAPH_HT_header,
+ GRAPH_MT_editor_menus,
+ GRAPH_MT_view,
+ GRAPH_MT_select,
+ GRAPH_MT_marker,
+ GRAPH_MT_channel,
+ GRAPH_MT_key,
+ GRAPH_MT_key_transform,
+ GRAPH_MT_delete,
+)
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 04b4cef9512..b274657b4f4 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -1242,5 +1242,59 @@ class IMAGE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Pan
bl_space_type = 'IMAGE_EDITOR'
+classes = (
+ IMAGE_MT_view,
+ IMAGE_MT_select,
+ IMAGE_MT_brush,
+ IMAGE_MT_image,
+ IMAGE_MT_image_invert,
+ IMAGE_MT_uvs,
+ IMAGE_MT_uvs_showhide,
+ IMAGE_MT_uvs_proportional,
+ IMAGE_MT_uvs_transform,
+ IMAGE_MT_uvs_snap,
+ IMAGE_MT_uvs_mirror,
+ IMAGE_MT_uvs_weldalign,
+ IMAGE_MT_uvs_select_mode,
+ IMAGE_HT_header,
+ MASK_MT_editor_menus,
+ IMAGE_PT_mask,
+ IMAGE_PT_mask_layers,
+ IMAGE_PT_mask_display,
+ IMAGE_PT_active_mask_spline,
+ IMAGE_PT_active_mask_point,
+ IMAGE_PT_image_properties,
+ IMAGE_PT_game_properties,
+ IMAGE_PT_view_properties,
+ IMAGE_PT_tools_transform_uvs,
+ IMAGE_PT_paint,
+ IMAGE_PT_tools_brush_overlay,
+ IMAGE_PT_tools_brush_texture,
+ IMAGE_PT_tools_mask,
+ IMAGE_PT_tools_mask_texture,
+ IMAGE_PT_tools_brush_tool,
+ IMAGE_PT_paint_stroke,
+ IMAGE_PT_paint_curve,
+ IMAGE_PT_tools_imagepaint_symmetry,
+ IMAGE_PT_tools_brush_appearance,
+ IMAGE_PT_tools_paint_options,
+ IMAGE_UV_sculpt,
+ IMAGE_UV_sculpt_curve,
+ IMAGE_PT_view_histogram,
+ IMAGE_PT_view_waveform,
+ IMAGE_PT_view_vectorscope,
+ IMAGE_PT_sample_line,
+ IMAGE_PT_scope_sample,
+ IMAGE_PT_grease_pencil,
+ IMAGE_PT_grease_pencil_palettecolor,
+ IMAGE_PT_tools_grease_pencil_draw,
+ IMAGE_PT_tools_grease_pencil_edit,
+ IMAGE_PT_tools_grease_pencil_sculpt,
+ IMAGE_PT_tools_grease_pencil_brush,
+ IMAGE_PT_tools_grease_pencil_brushcurves,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index fcb30130730..f986235cc90 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -127,6 +127,18 @@ class INFO_MT_file(Menu):
layout.operator("wm.save_homefile", icon='SAVE_PREFS')
layout.operator("wm.read_factory_settings", icon='LOAD_FACTORY')
+ if any(bpy.utils.app_template_paths()):
+ app_template = context.user_preferences.app_template
+ if app_template:
+ layout.operator(
+ "wm.read_factory_settings",
+ text="Load Factory Template Settings",
+ icon='LOAD_FACTORY',
+ ).app_template = app_template
+ del app_template
+
+ layout.menu("USERPREF_MT_app_templates", icon='FILE_BLEND')
+
layout.separator()
layout.operator_context = 'INVOKE_AREA'
@@ -281,7 +293,7 @@ class INFO_MT_window(Menu):
layout = self.layout
- layout.operator("wm.window_duplicate")
+ layout.operator("wm.window_new")
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER')
layout.separator()
@@ -340,5 +352,23 @@ class INFO_MT_help(Menu):
layout.operator("wm.splash", icon='BLENDER')
+
+classes = (
+ INFO_HT_header,
+ INFO_MT_editor_menus,
+ INFO_MT_file,
+ INFO_MT_file_import,
+ INFO_MT_file_export,
+ INFO_MT_file_external_data,
+ INFO_MT_file_previews,
+ INFO_MT_game,
+ INFO_MT_render,
+ INFO_MT_opengl_render,
+ INFO_MT_window,
+ INFO_MT_help,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py
index 1b316a3eede..b552181f491 100644
--- a/release/scripts/startup/bl_ui/space_logic.py
+++ b/release/scripts/startup/bl_ui/space_logic.py
@@ -130,5 +130,16 @@ class LOGIC_MT_view(Menu):
layout.operator("screen.screen_full_area")
layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
+
+classes = (
+ LOGIC_PT_properties,
+ LOGIC_MT_logicbricks_add,
+ LOGIC_HT_header,
+ LOGIC_MT_editor_menus,
+ LOGIC_MT_view,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 8fbf9bfc6ac..65d020477dc 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -209,5 +209,19 @@ class NLA_MT_edit_transform(Menu):
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
+
+classes = (
+ NLA_HT_header,
+ NLA_MT_edit,
+ NLA_MT_editor_menus,
+ NLA_MT_view,
+ NLA_MT_select,
+ NLA_MT_marker,
+ NLA_MT_add,
+ NLA_MT_edit_transform,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 8821fa0ca58..b939d34e154 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -526,6 +526,33 @@ class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Pane
def node_draw_tree_view(layout, context):
pass
+classes = (
+ NODE_HT_header,
+ NODE_MT_editor_menus,
+ NODE_MT_add,
+ NODE_MT_view,
+ NODE_MT_select,
+ NODE_MT_node,
+ NODE_MT_node_color_presets,
+ NODE_MT_node_color_specials,
+ NODE_PT_active_node_generic,
+ NODE_PT_active_node_color,
+ NODE_PT_active_node_properties,
+ NODE_PT_backdrop,
+ NODE_PT_quality,
+ NODE_UL_interface_sockets,
+ NODE_PT_grease_pencil,
+ NODE_PT_grease_pencil_palettecolor,
+ NODE_PT_grease_pencil_tools,
+ NODE_PT_tools_grease_pencil_draw,
+ NODE_PT_tools_grease_pencil_edit,
+ NODE_PT_tools_grease_pencil_sculpt,
+ NODE_PT_tools_grease_pencil_brush,
+ NODE_PT_tools_grease_pencil_brushcurves,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index eb3cef8012d..054a955ab9c 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -59,14 +59,16 @@ class OUTLINER_HT_header(Header):
row.label(text="No Keying Set active")
elif space.display_mode == 'ORPHAN_DATA':
layout.operator("outliner.orphans_purge")
- elif space.display_mode == 'COLLECTIONS':
+
+ elif space.display_mode in {'ACT_LAYER', 'MASTER_COLLECTION'}:
row = layout.row(align=True)
- row.operator("collections.collection_new", text="", icon='NEW')
- row.operator("collections.override_new", text="", icon='LINK_AREA')
- row.operator("collections.collection_link", text="", icon='LINKED')
- row.operator("collections.collection_unlink", text="", icon='UNLINKED')
- row.operator("collections.delete", text="", icon='X')
+ row.operator("outliner.collection_new", text="", icon='NEW')
+ if space.display_mode == 'ACT_LAYER':
+ row.operator("outliner.collection_override_new", text="", icon='LINK_AREA')
+ row.operator("outliner.collection_link", text="", icon='LINKED')
+ row.operator("outliner.collection_unlink", text="", icon='UNLINKED')
+ row.operator("outliner.collections_delete", text="", icon='X')
class OUTLINER_MT_editor_menus(Menu):
@@ -96,7 +98,8 @@ class OUTLINER_MT_view(Menu):
space = context.space_data
if space.display_mode not in {'DATABLOCKS', 'USER_PREFERENCES', 'KEYMAPS'}:
- layout.prop(space, "use_sort_alpha")
+ if space.display_mode not in {'ACT_LAYER', 'MASTER_COLLECTION'}:
+ layout.prop(space, "use_sort_alpha")
layout.prop(space, "show_restrict_columns")
layout.separator()
layout.operator("outliner.show_active")
@@ -138,5 +141,16 @@ class OUTLINER_MT_edit_datablocks(Menu):
layout.operator("outliner.drivers_add_selected")
layout.operator("outliner.drivers_delete_selected")
+
+classes = (
+ OUTLINER_HT_header,
+ OUTLINER_MT_editor_menus,
+ OUTLINER_MT_view,
+ OUTLINER_MT_search,
+ OUTLINER_MT_edit_datablocks,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_properties.py b/release/scripts/startup/bl_ui/space_properties.py
index f0ca01ec3ba..20cb5719e20 100644
--- a/release/scripts/startup/bl_ui/space_properties.py
+++ b/release/scripts/startup/bl_ui/space_properties.py
@@ -34,13 +34,11 @@ class PROPERTIES_HT_header(Header):
row.prop(view, "context", expand=True, icon_only=True)
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-
-if __name__ == "__main__":
- register()
+classes = (
+ PROPERTIES_HT_header,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 6bb516cf929..01da3b48f7d 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -652,17 +652,39 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
col.prop(strip, "rotation_start", text="Rotation")
elif strip.type == 'MULTICAM':
- layout.prop(strip, "multicam_source")
-
- row = layout.row(align=True)
- sub = row.row(align=True)
- sub.scale_x = 2.0
-
- sub.operator("screen.animation_play", text="", icon='PAUSE' if context.screen.is_animation_playing else 'PLAY')
+ col = layout.column(align=True)
+ strip_channel = strip.channel
+
+ col.prop(strip, "multicam_source", text="Source Channel")
+
+ # The multicam strip needs at least 2 strips to be useful
+ if strip_channel > 2:
+ BT_ROW = 4
+
+ col.label("Cut To:")
+ row = col.row()
+
+ for i in range(1, strip_channel):
+ if (i % BT_ROW) == 1:
+ row = col.row(align=True)
+
+ # Workaround - .enabled has to have a separate UI block to work
+ if i == strip.multicam_source:
+ sub = row.row(align=True)
+ sub.enabled = False
+ sub.operator("sequencer.cut_multicam", text="%d" % i).camera = i
+ else:
+ sub_1 = row.row(align=True)
+ sub_1.enabled = True
+ sub_1.operator("sequencer.cut_multicam", text="%d" % i).camera = i
+
+ if strip.channel > BT_ROW and (strip_channel - 1) % BT_ROW:
+ for i in range(strip.channel, strip_channel + ((BT_ROW + 1 - strip_channel) % BT_ROW)):
+ row.label("")
+ else:
+ col.separator()
+ col.label(text="Two or more channels are needed below this strip", icon="INFO")
- row.label("Cut To")
- for i in range(1, strip.channel):
- row.operator("sequencer.cut_multicam", text="%d" % i).camera = i
elif strip.type == 'TEXT':
col = layout.column()
@@ -1217,5 +1239,37 @@ class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel):
bl_category = "Strip"
+classes = (
+ SEQUENCER_HT_header,
+ SEQUENCER_MT_editor_menus,
+ SEQUENCER_MT_view,
+ SEQUENCER_MT_view_toggle,
+ SEQUENCER_MT_select,
+ SEQUENCER_MT_marker,
+ SEQUENCER_MT_change,
+ SEQUENCER_MT_frame,
+ SEQUENCER_MT_add,
+ SEQUENCER_MT_add_effect,
+ SEQUENCER_MT_strip,
+ SEQUENCER_PT_edit,
+ SEQUENCER_PT_effect,
+ SEQUENCER_PT_input,
+ SEQUENCER_PT_sound,
+ SEQUENCER_PT_scene,
+ SEQUENCER_PT_mask,
+ SEQUENCER_PT_filter,
+ SEQUENCER_PT_proxy,
+ SEQUENCER_PT_preview,
+ SEQUENCER_PT_view,
+ SEQUENCER_PT_view_safe_areas,
+ SEQUENCER_PT_modifiers,
+ SEQUENCER_PT_grease_pencil,
+ SEQUENCER_PT_grease_pencil_palettecolor,
+ SEQUENCER_PT_grease_pencil_tools,
+ SEQUENCER_PT_custom_props,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 1fd10575e07..98a7da855ca 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -215,20 +215,22 @@ class TEXT_MT_templates_py(Menu):
bl_label = "Python"
def draw(self, context):
- self.path_menu(bpy.utils.script_paths("templates_py"),
- "text.open",
- {"internal": True},
- )
+ self.path_menu(
+ bpy.utils.script_paths("templates_py"),
+ "text.open",
+ props_default={"internal": True},
+ )
class TEXT_MT_templates_osl(Menu):
bl_label = "Open Shading Language"
def draw(self, context):
- self.path_menu(bpy.utils.script_paths("templates_osl"),
- "text.open",
- {"internal": True},
- )
+ self.path_menu(
+ bpy.utils.script_paths("templates_osl"),
+ "text.open",
+ props_default={"internal": True},
+ )
class TEXT_MT_templates(Menu):
@@ -341,5 +343,25 @@ class TEXT_MT_toolbox(Menu):
layout.operator("text.run_script")
+
+classes = (
+ TEXT_HT_header,
+ TEXT_MT_edit,
+ TEXT_MT_editor_menus,
+ TEXT_PT_properties,
+ TEXT_PT_find,
+ TEXT_MT_view,
+ TEXT_MT_text,
+ TEXT_MT_templates,
+ TEXT_MT_templates_py,
+ TEXT_MT_templates_osl,
+ TEXT_MT_edit_select,
+ TEXT_MT_format,
+ TEXT_MT_edit_to3d,
+ TEXT_MT_toolbox,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 508e62e4f56..b9a25cd72a0 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -49,7 +49,10 @@ class TIME_HT_header(Header):
row.prop(scene, "frame_preview_start", text="Start")
row.prop(scene, "frame_preview_end", text="End")
- layout.prop(scene, "frame_current", text="")
+ if scene.show_subframe:
+ layout.prop(scene, "frame_float", text="")
+ else:
+ layout.prop(scene, "frame_current", text="")
layout.separator()
@@ -135,6 +138,7 @@ class TIME_MT_view(Menu):
layout.prop(st, "show_frame_indicator")
layout.prop(scene, "show_keys_from_selected_only")
+ layout.prop(scene, "show_subframe")
layout.separator()
@@ -265,5 +269,18 @@ def marker_menu_generic(layout):
layout.prop(ts, "lock_markers")
+classes = (
+ TIME_HT_header,
+ TIME_MT_editor_menus,
+ TIME_MT_marker,
+ TIME_MT_view,
+ TIME_MT_cache,
+ TIME_MT_frame,
+ TIME_MT_playback,
+ TIME_MT_autokey,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 075a6f870fa..e50beba50d8 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -90,6 +90,63 @@ class USERPREF_MT_interaction_presets(Menu):
draw = Menu.draw_preset
+class USERPREF_MT_app_templates(Menu):
+ bl_label = "Application Templates"
+ preset_subdir = "app_templates"
+
+ def draw_ex(self, context, *, use_splash=False, use_default=False, use_install=False):
+ import os
+
+ layout = self.layout
+
+ # now draw the presets
+ layout.operator_context = 'EXEC_DEFAULT'
+
+ if use_default:
+ props = layout.operator("wm.read_homefile", text="Default")
+ props.use_splash = True
+ props.app_template = ""
+ layout.separator()
+
+ template_paths = bpy.utils.app_template_paths()
+
+ # expand template paths
+ app_templates = []
+ for path in template_paths:
+ for d in os.listdir(path):
+ if d.startswith(("__", ".")):
+ continue
+ template = os.path.join(path, d)
+ if os.path.isdir(template):
+ # template_paths_expand.append(template)
+ app_templates.append(d)
+
+ for d in sorted(app_templates):
+ props = layout.operator(
+ "wm.read_homefile",
+ text=bpy.path.display_name(d),
+ )
+ props.use_splash = True
+ props.app_template = d;
+
+ if use_install:
+ layout.separator()
+ layout.operator_context = 'INVOKE_DEFAULT'
+ props = layout.operator("wm.app_template_install")
+
+
+ def draw(self, context):
+ self.draw_ex(context, use_splash=False, use_default=True, use_install=True)
+
+
+class USERPREF_MT_templates_splash(Menu):
+ bl_label = "Startup Templates"
+ preset_subdir = "templates"
+
+ def draw(self, context):
+ USERPREF_MT_app_templates.draw_ex(self, context, use_splash=True, use_default=True)
+
+
class USERPREF_MT_appconfigs(Menu):
bl_label = "AppPresets"
preset_subdir = "keyconfig"
@@ -110,7 +167,17 @@ class USERPREF_MT_splash(Menu):
split = layout.split()
row = split.row()
- row.label("")
+
+ if any(bpy.utils.app_template_paths()):
+ row.label("Template:")
+ template = context.user_preferences.app_template
+ row.menu(
+ "USERPREF_MT_templates_splash",
+ text=bpy.path.display_name(template) if template else "Default",
+ )
+ else:
+ row.label("")
+
row = split.row()
row.label("Interaction:")
@@ -150,6 +217,7 @@ class USERPREF_PT_interface(Panel):
col = row.column()
col.label(text="Display:")
+ col.prop(view, "ui_scale", text="Scale")
col.prop(view, "show_tooltips")
col.prop(view, "show_tooltips_python")
col.prop(view, "show_object_info", text="Object Info")
@@ -400,11 +468,6 @@ class USERPREF_PT_system(Panel):
col = colsplit.column()
col.label(text="General:")
- col.prop(system, "dpi")
- col.label("Virtual Pixel Mode:")
- col.prop(system, "virtual_pixel_mode", text="")
-
- col.separator()
col.prop(system, "frame_server_port")
col.prop(system, "scrollback", text="Console Scrollback")
@@ -453,6 +516,7 @@ class USERPREF_PT_system(Panel):
col.separator()
col.label(text="Selection")
col.prop(system, "select_method", text="")
+ col.prop(system, "use_select_pick_depth")
col.separator()
@@ -1243,7 +1307,7 @@ class USERPREF_MT_addons_online_resources(Menu):
"wm.url_open", text="API Concepts", icon='URL',
).url = bpy.types.WM_OT_doc_view._prefix + "/info_quickstart.html"
layout.operator("wm.url_open", text="Add-on Tutorial", icon='URL',
- ).url = "http://www.blender.org/api/blender_python_api_current/info_tutorial_addon.html"
+ ).url = bpy.types.WM_OT_doc_view._prefix + "/info_tutorial_addon.html"
class USERPREF_PT_addons(Panel):
@@ -1317,11 +1381,18 @@ class USERPREF_PT_addons(Panel):
# set in addon_utils.modules_refresh()
if addon_utils.error_duplicates:
- self.draw_error(col,
- "Multiple addons using the same name found!\n"
- "likely a problem with the script search path.\n"
- "(see console for details)",
- )
+ box = col.box()
+ row = box.row()
+ row.label("Multiple add-ons with the same name found!")
+ row.label(icon='ERROR')
+ box.label("Please delete one of each pair:")
+ for (addon_name, addon_file, addon_path) in addon_utils.error_duplicates:
+ box.separator()
+ sub_col = box.column(align=True)
+ sub_col.label(addon_name + ":")
+ sub_col.label(" " + addon_file)
+ sub_col.label(" " + addon_path)
+
if addon_utils.error_encoding:
self.draw_error(col,
@@ -1473,5 +1544,29 @@ class USERPREF_PT_addons(Panel):
row.label(text=module_name, translate=False)
+classes = (
+ USERPREF_HT_header,
+ USERPREF_PT_tabs,
+ USERPREF_MT_interaction_presets,
+ USERPREF_MT_templates_splash,
+ USERPREF_MT_app_templates,
+ USERPREF_MT_appconfigs,
+ USERPREF_MT_splash,
+ USERPREF_MT_splash_footer,
+ USERPREF_PT_interface,
+ USERPREF_PT_edit,
+ USERPREF_PT_system,
+ USERPREF_MT_interface_theme_presets,
+ USERPREF_PT_theme,
+ USERPREF_PT_file,
+ USERPREF_MT_ndof_settings,
+ USERPREF_MT_keyconfigs,
+ USERPREF_PT_input,
+ USERPREF_MT_addons_online_resources,
+ USERPREF_PT_addons,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index f605712510a..1ede823e6d8 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -284,7 +284,8 @@ class VIEW3D_MT_transform_object(VIEW3D_MT_transform_base):
layout.separator()
layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator("transform.transform", text="Align to Transform Orientation").mode = 'ALIGN' # XXX see alignmenu() in edit.c of b2.4x to get this working
+ # XXX see alignmenu() in edit.c of b2.4x to get this working
+ layout.operator("transform.transform", text="Align to Transform Orientation").mode = 'ALIGN'
layout.separator()
@@ -1203,6 +1204,16 @@ class INFO_MT_lamp_add(Menu):
layout.operator_enum("object.lamp_add", "type")
+class INFO_MT_camera_add(Menu):
+ bl_idname = "INFO_MT_camera_add"
+ bl_label = "Camera"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator_context = 'EXEC_REGION_WIN'
+ layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
+
+
class INFO_MT_add(Menu):
bl_label = "Add"
@@ -1234,7 +1245,11 @@ class INFO_MT_add(Menu):
layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
layout.separator()
- layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
+ if INFO_MT_camera_add.is_extended():
+ layout.menu("INFO_MT_camera_add", icon='OUTLINER_OB_CAMERA')
+ else:
+ INFO_MT_camera_add.draw(self, context)
+
layout.menu("INFO_MT_lamp_add", icon='OUTLINER_OB_LAMP')
layout.separator()
@@ -1522,6 +1537,7 @@ class VIEW3D_MT_object_apply(Menu):
layout.separator()
layout.operator("object.visual_transform_apply", text="Visual Transform", text_ctxt=i18n_contexts.default)
+ layout.operator("object.convert", text="Visual Geometry to Mesh", text_ctxt=i18n_contexts.default).target = 'MESH'
layout.operator("object.duplicates_make_real")
@@ -1722,6 +1738,7 @@ class VIEW3D_MT_brush_paint_modes(Menu):
layout.prop(brush, "use_paint_weight", text="Weight Paint")
layout.prop(brush, "use_paint_image", text="Texture Paint")
+
# ********** Vertex paint menu **********
@@ -1791,6 +1808,7 @@ class VIEW3D_MT_vertex_group(Menu):
layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
+
# ********** Weight paint menu **********
@@ -1829,6 +1847,7 @@ class VIEW3D_MT_paint_weight(Menu):
layout.operator("paint.weight_set")
+
# ********** Sculpt menu **********
@@ -1982,6 +2001,7 @@ class VIEW3D_MT_particle_specials(Menu):
class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
_operator_name = "particle"
+
# ********** Pose Menu **********
@@ -2255,6 +2275,7 @@ class VIEW3D_MT_bone_options_disable(Menu, BoneOptions):
bl_label = "Disable Bone Options"
type = 'DISABLE'
+
# ********** Edit Menus, suffix from ob.type **********
@@ -2422,6 +2443,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
with_bullet = bpy.app.build_options.bullet
layout.operator("mesh.merge")
+ layout.operator("mesh.remove_doubles")
layout.operator("mesh.rip_move")
layout.operator("mesh.rip_move_fill")
layout.operator("mesh.rip_edge_move")
@@ -2444,7 +2466,6 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
if with_bullet:
layout.operator("mesh.convex_hull")
layout.operator("mesh.vertices_smooth")
- layout.operator("mesh.remove_doubles")
layout.operator("mesh.blend_from_shape")
@@ -2601,6 +2622,7 @@ class VIEW3D_MT_edit_mesh_clean(Menu):
layout.operator("mesh.face_make_planar")
layout.operator("mesh.vert_connect_nonplanar")
layout.operator("mesh.vert_connect_concave")
+ layout.operator("mesh.remove_doubles")
layout.operator("mesh.fill_holes")
@@ -3146,74 +3168,6 @@ class VIEW3D_PT_viewport_debug(Panel):
col.row(align=True).prop(view, "debug_background", expand=True)
-class VIEW3D_PT_collections_editor(Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
- bl_label = "Collections"
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- return context.space_data
-
- def draw(self, context):
- layout = self.layout
- layer = context.render_layer
- active_collection = context.layer_collection
-
- col = layout.column()
- box = col.box()
-
- index = -1
- for collection in layer.collections:
- index = self._draw_layer_collection(box, index, active_collection, collection, True, True)
-
- row = layout.row(align=True)
- row.operator("collections.collection_new", text="", icon='NEW')
- row.operator("collections.override_new", text="", icon='LINK_AREA')
- row.operator("collections.collection_link", text="", icon='LINKED')
- row.operator("collections.collection_unlink", text="", icon='UNLINKED')
- row.operator("collections.delete", text="", icon='X')
-
- def _draw_layer_collection(self, box, index, active_collection, collection, is_active, is_draw, depth=0):
- index += 1
- nested_collections = collection.collections
-
- if is_draw:
- row = box.row()
- row.active = is_active
- is_collection_selected = (collection == active_collection)
-
- if is_collection_selected:
- sub_box = row.box()
- row = sub_box.row()
-
- row.label(text="{0}{1}{2}".format(
- " " * depth,
- u'\u21b3 ' if depth else "",
- collection.name))
-
- row.prop(collection, "hide", text="", emboss=False)
- row.prop(collection, "hide_select", text="", emboss=False)
-
- row.operator("collections.select", text="", icon='BLANK1' if is_collection_selected else 'HAND', emboss=False).collection_index=index
-
- if nested_collections:
- row.prop(collection, "is_unfolded", text="", emboss=False)
- else:
- row.label(icon='BLANK1')
-
- if not collection.is_unfolded:
- is_draw = False
-
- is_active &= not collection.hide
-
- for nested_collection in nested_collections:
- index = self._draw_layer_collection(box, index, active_collection, nested_collection, is_active, is_draw, depth + 1)
-
- return index
-
-
class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -3872,13 +3826,143 @@ class VIEW3D_PT_context_properties(Panel):
# Draw with no edit button
rna_prop_ui.draw(self.layout, context, member, object, False)
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
+classes = (
+ VIEW3D_HT_header,
+ VIEW3D_MT_editor_menus,
+ VIEW3D_MT_transform,
+ VIEW3D_MT_transform_base,
+ VIEW3D_MT_transform_object,
+ VIEW3D_MT_transform_armature,
+ VIEW3D_MT_mirror,
+ VIEW3D_MT_snap,
+ VIEW3D_MT_uv_map,
+ VIEW3D_MT_edit_proportional,
+ VIEW3D_MT_view,
+ VIEW3D_MT_view_navigation,
+ VIEW3D_MT_view_align,
+ VIEW3D_MT_view_align_selected,
+ VIEW3D_MT_view_cameras,
+ VIEW3D_MT_select_object,
+ VIEW3D_MT_select_object_more_less,
+ VIEW3D_MT_select_pose,
+ VIEW3D_MT_select_pose_more_less,
+ VIEW3D_MT_select_particle,
+ VIEW3D_MT_edit_mesh,
+ VIEW3D_MT_edit_mesh_select_similar,
+ VIEW3D_MT_edit_mesh_select_by_trait,
+ VIEW3D_MT_edit_mesh_select_more_less,
+ VIEW3D_MT_select_edit_mesh,
+ VIEW3D_MT_select_edit_curve,
+ VIEW3D_MT_select_edit_surface,
+ VIEW3D_MT_select_edit_text,
+ VIEW3D_MT_select_edit_metaball,
+ VIEW3D_MT_select_edit_lattice,
+ VIEW3D_MT_select_edit_armature,
+ VIEW3D_MT_select_gpencil,
+ VIEW3D_MT_select_paint_mask,
+ VIEW3D_MT_select_paint_mask_vertex,
+ VIEW3D_MT_angle_control,
+ INFO_MT_mesh_add,
+ INFO_MT_curve_add,
+ INFO_MT_surface_add,
+ INFO_MT_metaball_add,
+ INFO_MT_edit_curve_add,
+ INFO_MT_edit_armature_add,
+ INFO_MT_armature_add,
+ INFO_MT_lamp_add,
+ INFO_MT_camera_add,
+ INFO_MT_add,
+ VIEW3D_MT_object,
+ VIEW3D_MT_object_animation,
+ VIEW3D_MT_object_clear,
+ VIEW3D_MT_object_specials,
+ VIEW3D_MT_object_apply,
+ VIEW3D_MT_object_parent,
+ VIEW3D_MT_object_track,
+ VIEW3D_MT_object_group,
+ VIEW3D_MT_object_constraints,
+ VIEW3D_MT_object_quick_effects,
+ VIEW3D_MT_make_single_user,
+ VIEW3D_MT_make_links,
+ VIEW3D_MT_object_game,
+ VIEW3D_MT_brush,
+ VIEW3D_MT_brush_paint_modes,
+ VIEW3D_MT_paint_vertex,
+ VIEW3D_MT_hook,
+ VIEW3D_MT_vertex_group,
+ VIEW3D_MT_paint_weight,
+ VIEW3D_MT_sculpt,
+ VIEW3D_MT_hide_mask,
+ VIEW3D_MT_particle,
+ VIEW3D_MT_particle_specials,
+ VIEW3D_MT_particle_showhide,
+ VIEW3D_MT_pose,
+ VIEW3D_MT_pose_transform,
+ VIEW3D_MT_pose_slide,
+ VIEW3D_MT_pose_propagate,
+ VIEW3D_MT_pose_library,
+ VIEW3D_MT_pose_motion,
+ VIEW3D_MT_pose_group,
+ VIEW3D_MT_pose_ik,
+ VIEW3D_MT_pose_constraints,
+ VIEW3D_MT_pose_showhide,
+ VIEW3D_MT_pose_apply,
+ VIEW3D_MT_pose_specials,
+ VIEW3D_MT_bone_options_toggle,
+ VIEW3D_MT_bone_options_enable,
+ VIEW3D_MT_bone_options_disable,
+ VIEW3D_MT_edit_mesh_specials,
+ VIEW3D_MT_edit_mesh_select_mode,
+ VIEW3D_MT_edit_mesh_extrude,
+ VIEW3D_MT_edit_mesh_vertices,
+ VIEW3D_MT_edit_mesh_edges,
+ VIEW3D_MT_edit_mesh_faces,
+ VIEW3D_MT_edit_mesh_normals,
+ VIEW3D_MT_edit_mesh_clean,
+ VIEW3D_MT_edit_mesh_delete,
+ VIEW3D_MT_edit_mesh_showhide,
+ VIEW3D_MT_edit_gpencil,
+ VIEW3D_MT_edit_gpencil_delete,
+ VIEW3D_MT_edit_curve,
+ VIEW3D_MT_edit_curve_ctrlpoints,
+ VIEW3D_MT_edit_curve_segments,
+ VIEW3D_MT_edit_curve_specials,
+ VIEW3D_MT_edit_curve_delete,
+ VIEW3D_MT_edit_curve_showhide,
+ VIEW3D_MT_edit_surface,
+ VIEW3D_MT_edit_font,
+ VIEW3D_MT_edit_text_chars,
+ VIEW3D_MT_edit_meta,
+ VIEW3D_MT_edit_meta_showhide,
+ VIEW3D_MT_edit_lattice,
+ VIEW3D_MT_edit_armature,
+ VIEW3D_MT_armature_specials,
+ VIEW3D_MT_edit_armature_parent,
+ VIEW3D_MT_edit_armature_roll,
+ VIEW3D_MT_edit_armature_delete,
+ VIEW3D_MT_edit_gpencil_transform,
+ VIEW3D_MT_edit_gpencil_interpolate,
+ VIEW3D_PT_viewport_debug,
+ VIEW3D_PT_grease_pencil,
+ VIEW3D_PT_grease_pencil_palettecolor,
+ VIEW3D_PT_view3d_properties,
+ VIEW3D_PT_view3d_cursor,
+ VIEW3D_PT_view3d_name,
+ VIEW3D_PT_view3d_display,
+ VIEW3D_PT_view3d_stereo,
+ VIEW3D_PT_view3d_shading,
+ VIEW3D_PT_view3d_motion_tracking,
+ VIEW3D_PT_view3d_meshdisplay,
+ VIEW3D_PT_view3d_meshstatvis,
+ VIEW3D_PT_view3d_curvedisplay,
+ VIEW3D_PT_background_image,
+ VIEW3D_PT_transform_orientations,
+ VIEW3D_PT_etch_a_ton,
+ VIEW3D_PT_context_properties,
+)
+
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 60e86d7544d..d58453deaef 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -2008,5 +2008,69 @@ class VIEW3D_PT_tools_history(View3DPanel, Panel):
col.operator("screen.repeat_history", text="History...")
+classes = (
+ VIEW3D_PT_tools_transform,
+ VIEW3D_PT_tools_object,
+ VIEW3D_PT_tools_add_object,
+ VIEW3D_PT_tools_relations,
+ VIEW3D_PT_tools_animation,
+ VIEW3D_PT_tools_rigid_body,
+ VIEW3D_PT_tools_transform_mesh,
+ VIEW3D_PT_tools_meshedit,
+ VIEW3D_PT_tools_meshweight,
+ VIEW3D_PT_tools_add_mesh_edit,
+ VIEW3D_PT_tools_shading,
+ VIEW3D_PT_tools_uvs,
+ VIEW3D_PT_tools_meshedit_options,
+ VIEW3D_PT_tools_transform_curve,
+ VIEW3D_PT_tools_curveedit,
+ VIEW3D_PT_tools_add_curve_edit,
+ VIEW3D_PT_tools_curveedit_options_stroke,
+ VIEW3D_PT_tools_transform_surface,
+ VIEW3D_PT_tools_surfaceedit,
+ VIEW3D_PT_tools_add_surface_edit,
+ VIEW3D_PT_tools_textedit,
+ VIEW3D_PT_tools_armatureedit,
+ VIEW3D_PT_tools_armatureedit_transform,
+ VIEW3D_PT_tools_armatureedit_options,
+ VIEW3D_PT_tools_mballedit,
+ VIEW3D_PT_tools_add_mball_edit,
+ VIEW3D_PT_tools_latticeedit,
+ VIEW3D_PT_tools_posemode,
+ VIEW3D_PT_tools_posemode_options,
+ VIEW3D_PT_imapaint_tools_missing,
+ VIEW3D_PT_tools_brush,
+ TEXTURE_UL_texpaintslots,
+ VIEW3D_MT_tools_projectpaint_uvlayer,
+ VIEW3D_PT_slots_projectpaint,
+ VIEW3D_PT_stencil_projectpaint,
+ VIEW3D_PT_tools_brush_overlay,
+ VIEW3D_PT_tools_brush_texture,
+ VIEW3D_PT_tools_mask_texture,
+ VIEW3D_PT_tools_brush_stroke,
+ VIEW3D_PT_tools_brush_curve,
+ VIEW3D_PT_sculpt_dyntopo,
+ VIEW3D_PT_sculpt_options,
+ VIEW3D_PT_sculpt_symmetry,
+ VIEW3D_PT_tools_brush_appearance,
+ VIEW3D_PT_tools_weightpaint,
+ VIEW3D_PT_tools_weightpaint_options,
+ VIEW3D_PT_tools_vertexpaint,
+ VIEW3D_PT_tools_imagepaint_external,
+ VIEW3D_PT_tools_imagepaint_symmetry,
+ VIEW3D_PT_tools_projectpaint,
+ VIEW3D_MT_tools_projectpaint_stencil,
+ VIEW3D_PT_tools_particlemode,
+ VIEW3D_PT_tools_grease_pencil_draw,
+ VIEW3D_PT_tools_grease_pencil_edit,
+ VIEW3D_PT_tools_grease_pencil_interpolate,
+ VIEW3D_PT_tools_grease_pencil_sculpt,
+ VIEW3D_PT_tools_grease_pencil_brush,
+ VIEW3D_PT_tools_grease_pencil_brushcurves,
+ VIEW3D_PT_tools_history,
+)
+
if __name__ == "__main__": # only for live edit.
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 97320e56378..ce0b1b62d44 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -643,13 +643,41 @@ class BUILTIN_KSI_DeltaScale(KeyingSetInfo):
###############################
+classes = (
+ BUILTIN_KSI_Available,
+ BUILTIN_KSI_BendyBones,
+ BUILTIN_KSI_DeltaLocation,
+ BUILTIN_KSI_DeltaRotation,
+ BUILTIN_KSI_DeltaScale,
+ BUILTIN_KSI_LocRot,
+ BUILTIN_KSI_LocRotScale,
+ BUILTIN_KSI_LocScale,
+ BUILTIN_KSI_Location,
+ BUILTIN_KSI_RotScale,
+ BUILTIN_KSI_Rotation,
+ BUILTIN_KSI_Scaling,
+ BUILTIN_KSI_VisualLoc,
+ BUILTIN_KSI_VisualLocRot,
+ BUILTIN_KSI_VisualLocRotScale,
+ BUILTIN_KSI_VisualLocScale,
+ BUILTIN_KSI_VisualRot,
+ BUILTIN_KSI_VisualRotScale,
+ BUILTIN_KSI_VisualScaling,
+ BUILTIN_KSI_WholeCharacter,
+ BUILTIN_KSI_WholeCharacterSelected,
+)
+
def register():
- bpy.utils.register_module(__name__)
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
def unregister():
- bpy.utils.unregister_module(__name__)
+ from bpy.utils import unregister_class
+ for cls in classes:
+ unregister_class(cls)
if __name__ == "__main__":
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index e915aa5bb72..afc6e5455c4 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -19,7 +19,11 @@
# <pep8 compliant>
import bpy
import nodeitems_utils
-from nodeitems_utils import NodeCategory, NodeItem, NodeItemCustom
+from nodeitems_utils import (
+ NodeCategory,
+ NodeItem,
+ NodeItemCustom,
+)
# Subclasses for standard node types
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 47ebed8f791..9b27f780075 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lamp_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_lattice_types.h
+ ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_layer_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_linestyle_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_listBase.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_material_types.h
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc
index 0985a06d732..5f8fc1a3739 100644
--- a/source/blender/alembic/intern/abc_archive.cc
+++ b/source/blender/alembic/intern/abc_archive.cc
@@ -113,25 +113,25 @@ static OArchive create_archive(std::ostream *ostream,
Alembic::Abc::MetaData &md,
bool ogawa)
{
- md.set(Alembic::Abc::kApplicationNameKey, "Blender");
+ md.set(Alembic::Abc::kApplicationNameKey, "Blender");
md.set(Alembic::Abc::kUserDescriptionKey, scene_name);
- time_t raw_time;
- time(&raw_time);
- char buffer[128];
+ time_t raw_time;
+ time(&raw_time);
+ char buffer[128];
#if defined _WIN32 || defined _WIN64
- ctime_s(buffer, 128, &raw_time);
+ ctime_s(buffer, 128, &raw_time);
#else
- ctime_r(&raw_time, buffer);
+ ctime_r(&raw_time, buffer);
#endif
- const std::size_t buffer_len = strlen(buffer);
- if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
- buffer[buffer_len - 1] = '\0';
- }
+ const std::size_t buffer_len = strlen(buffer);
+ if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') {
+ buffer[buffer_len - 1] = '\0';
+ }
- md.set(Alembic::Abc::kDateWrittenKey, buffer);
+ md.set(Alembic::Abc::kDateWrittenKey, buffer);
ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc
index 282777f3af0..0542255d84b 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_curves.cc
@@ -361,7 +361,7 @@ void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time)
* object directly and create a new DerivedMesh from that. Also we might need to
* create new or delete existing NURBS in the curve.
*/
-DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh */*dm*/, const float time, int /*read_flag*/, const char **/*err_str*/)
+DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float time, int /*read_flag*/, const char ** /*err_str*/)
{
ISampleSelector sample_sel(time);
const ICurvesSchema::Sample sample = m_curves_schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index ebf1b2ba96e..0d11ab79ddd 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -327,6 +327,11 @@ static void read_custom_data_ex(const ICompoundProperty &prop,
}
else if (data_type == CD_MLOOPUV) {
IV2fGeomParam uv_param(prop, prop_header.getName());
+
+ if (!uv_param.isIndexed()) {
+ return;
+ }
+
IV2fGeomParam::Sample sample;
uv_param.getIndexed(sample, iss);
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index 28d54672d20..9986db89131 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -47,7 +47,7 @@ extern "C" {
#ifdef WIN32
/* needed for MSCV because of snprintf from BLI_string */
-# include "BLI_winstuff.h"
+# include "BLI_winstuff.h"
#endif
#include "BKE_anim.h"
@@ -341,11 +341,11 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled)
void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
{
- for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
+ for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
Object *ob = base->object;
if (export_object(&m_settings, base)) {
- switch(ob->type) {
+ switch (ob->type) {
case OB_LAMP:
case OB_LATTICE:
case OB_MBALL:
@@ -362,7 +362,7 @@ void AbcExporter::createTransformWritersHierarchy(EvaluationContext *eval_ctx)
void AbcExporter::createTransformWritersFlat()
{
- for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
+ for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
Object *ob = base->object;
if (!export_object(&m_settings, base)) {
@@ -412,7 +412,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
BLI_assert(ob != dupliObParent);
/* check if we have already created a transform writer for this object */
- if (getXForm(name) != NULL){
+ if (getXForm(name) != NULL) {
std::cerr << "xform " << name << " already exists\n";
return;
}
@@ -454,7 +454,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl
void AbcExporter::createShapeWriters(EvaluationContext *eval_ctx)
{
- for(Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
+ for (Base *base = static_cast<Base *>(m_settings.sl->object_bases.first); base; base = base->next) {
exploreObject(eval_ctx, base, NULL);
}
}
@@ -525,7 +525,7 @@ void AbcExporter::createShapeWriter(Base *ob_base, Object *dupliObParent)
}
}
- switch(ob->type) {
+ switch (ob->type) {
case OB_MESH:
{
Mesh *me = static_cast<Mesh *>(ob->data);
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 8bc9c335054..5a57e43326a 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -691,7 +691,7 @@ static void assign_materials(Main *bmain, Object *ob, const std::map<std::string
assigned_name = mat_iter->second;
}
- assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBJECT);
+ assign_material(ob, assigned_name, it->second, BKE_MAT_ASSIGN_OBDATA);
}
}
}
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc
index 4c78f3e83c7..fc84759b1d9 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_points.cc
@@ -200,7 +200,7 @@ void read_points_sample(const IPointsSchema &schema,
read_mverts(config.mvert, positions, vnormals);
}
-DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char **/*err_str*/)
+DerivedMesh *AbcPointsReader::read_derivedmesh(DerivedMesh *dm, const float time, int /*read_flag*/, const char ** /*err_str*/)
{
ISampleSelector sample_sel(time);
const IPointsSchema::Sample sample = m_schema.getValue(sample_sel);
diff --git a/source/blender/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_transform.cc
index e2fc7674c4e..2c6ef09326c 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_transform.cc
@@ -122,7 +122,7 @@ Imath::Box3d AbcTransformWriter::bounds()
return Imath::transform(bounds, m_matrix);
}
-bool AbcTransformWriter::hasAnimation(Object */*ob*/) const
+bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const
{
/* TODO(kevin): implement this. */
return true;
@@ -146,6 +146,6 @@ bool AbcEmptyReader::valid() const
void AbcEmptyReader::readObjectData(Main *bmain, float /*time*/)
{
- m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
+ m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_data_name.c_str());
m_object->data = NULL;
}
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index bb375eb9561..5b45dff4b7f 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -38,6 +38,8 @@ extern "C" {
#include "DNA_layer_types.h"
#include "BLI_math.h"
+
+#include "PIL_time.h"
}
std::string get_id_name(Object *ob)
@@ -512,3 +514,15 @@ AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSe
return reader;
}
+
+/* ********************** */
+
+ScopeTimer::ScopeTimer(const char *message)
+ : m_message(message)
+ , m_start(PIL_check_seconds_timer())
+{}
+
+ScopeTimer::~ScopeTimer()
+{
+ fprintf(stderr, "%s: %fs\n", m_message, PIL_check_seconds_timer() - m_start);
+}
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index 328f2c41a87..a878029928c 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -146,4 +146,23 @@ ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
yup[2] = -zup[1];
}
+/* *************************** */
+
+#undef ABC_DEBUG_TIME
+
+class ScopeTimer {
+ const char *m_message;
+ double m_start;
+
+public:
+ ScopeTimer(const char *message);
+ ~ScopeTimer();
+};
+
+#ifdef ABC_DEBUG_TIME
+# define SCOPE_TIMER(message) ScopeTimer prof(message)
+#else
+# define SCOPE_TIMER(message)
+#endif
+
#endif /* __ABC_UTIL_H__ */
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index fcfe634924f..ee8ec0fa68c 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -558,6 +558,8 @@ ABC_INLINE bool is_mesh_and_strands(const IObject &object)
static void import_startjob(void *user_data, short *stop, short *do_update, float *progress)
{
+ SCOPE_TIMER("Alembic import, objects reading and creation");
+
ImportJobData *data = static_cast<ImportJobData *>(user_data);
data->stop = stop;
@@ -693,6 +695,8 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
static void import_endjob(void *user_data)
{
+ SCOPE_TIMER("Alembic import, cleanup");
+
ImportJobData *data = static_cast<ImportJobData *>(user_data);
std::vector<AbcObjectReader *>::iterator iter;
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index ab7c831f95c..d4bd1502417 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -552,10 +552,10 @@ static void blf_draw_gl__start(FontBLF *font)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
if (font->flags & BLF_MATRIX)
- gpuMultMatrix3D((float (*)[4])font->m);
+ gpuMultMatrix3D(font->m);
gpuTranslate3fv(font->pos);
@@ -563,7 +563,7 @@ static void blf_draw_gl__start(FontBLF *font)
gpuScale3fv(font->aspect);
if (font->flags & BLF_ROTATION) /* radians -> degrees */
- gpuRotateAxis(RAD2DEG(font->angle), 'Z');
+ gpuRotateAxis(RAD2DEG(font->angle), 'Z'); /* TODO: use gpuRotate2D here? */
#ifndef BLF_STANDALONE
VertexFormat *format = immVertexFormat();
@@ -584,7 +584,7 @@ static void blf_draw_gl__start(FontBLF *font)
static void blf_draw_gl__end(void)
{
- gpuMatrixEnd();
+ gpuPopMatrix();
#ifndef BLF_STANDALONE
immUnbindProgram();
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index b1bab13f3ae..fa37f88d91f 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -438,14 +438,21 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
}
- glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
+ GLint lsb_first, row_length, alignment;
+ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsb_first);
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
+
glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBindTexture(GL_TEXTURE_2D, g->tex);
glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap);
- glPopClientAttrib();
+
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsb_first);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
g->uv[0][0] = ((float)g->xoff) / ((float)gc->p2_width);
g->uv[0][1] = ((float)g->yoff) / ((float)gc->p2_height);
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 789bc8df7e5..c7bcf036f5b 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -387,9 +387,6 @@ struct DerivedMesh {
/** Draw all vertices as bgl points (no options) */
void (*drawVerts)(DerivedMesh *dm);
- /** Draw edges in the UV mesh (if exists) */
- void (*drawUVEdges)(DerivedMesh *dm);
-
/** Draw all edges as lines (no options)
*
* Also called for *final* editmode DerivedMeshes
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index 077fe2a629c..ac8f861fa56 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -27,11 +27,15 @@
/* note on naming: typical _get() suffix is omitted here,
* since its the main purpose of the API. */
const char *BKE_appdir_folder_default(void);
+const char *BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, size_t path_len);
const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder);
const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check);
+bool BKE_appdir_app_template_any(void);
+bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len);
+
/* Initialize path to program executable */
void BKE_appdir_program_path_init(const char *argv0);
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h
index d2d9c763031..d55926ffb1e 100644
--- a/source/blender/blenkernel/BKE_blender.h
+++ b/source/blender/blenkernel/BKE_blender.h
@@ -38,14 +38,22 @@
extern "C" {
#endif
+struct UserDef;
+
void BKE_blender_free(void);
void BKE_blender_globals_init(void);
void BKE_blender_globals_clear(void);
+void BKE_blender_version_string(
+ char *version_str, size_t maxncpy,
+ short version, short subversion, bool v_prefix, bool include_subversion);
-void BKE_blender_userdef_free(void);
+void BKE_blender_userdef_set_data(struct UserDef *userdef);
+void BKE_blender_userdef_free_data(struct UserDef *userdef);
void BKE_blender_userdef_refresh(void);
-
+
+void BKE_blender_userdef_set_app_template(struct UserDef *userdef);
+
/* set this callback when a UI is running */
void BKE_blender_callback_test_break_set(void (*func)(void));
int BKE_blender_test_break(void);
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 4f4787f9da5..bc3db11f34b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,8 +27,8 @@
/* these lines are grep'd, watch out for our not-so-awesome regex
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
-#define BLENDER_VERSION 278
-#define BLENDER_SUBVERSION 4
+#define BLENDER_VERSION 280
+#define BLENDER_SUBVERSION 0
/* Several breakages with 270, e.g. constraint deg vs rad */
#define BLENDER_MINVERSION 270
#define BLENDER_MINSUBVERSION 6
diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h
index 6767fce3abd..ac58451e412 100644
--- a/source/blender/blenkernel/BKE_blendfile.h
+++ b/source/blender/blenkernel/BKE_blendfile.h
@@ -33,8 +33,7 @@ struct ID;
struct Main;
struct MemFile;
struct ReportList;
-
-int BKE_blendfile_read(struct bContext *C, const char *filepath, struct ReportList *reports);
+struct UserDef;
enum {
BKE_BLENDFILE_READ_FAIL = 0, /* no load */
@@ -42,15 +41,24 @@ enum {
BKE_BLENDFILE_READ_OK_USERPREFS = 2, /* OK, and with new user settings */
};
+int BKE_blendfile_read(
+ struct bContext *C, const char *filepath,
+ struct ReportList *reports, int skip_flag);
bool BKE_blendfile_read_from_memory(
- struct bContext *C, const void *filebuf,
- int filelength, struct ReportList *reports, bool update_defaults);
+ struct bContext *C, const void *filebuf, int filelength,
+ struct ReportList *reports, int skip_flag, bool update_defaults);
bool BKE_blendfile_read_from_memfile(
struct bContext *C, struct MemFile *memfile,
+ struct ReportList *reports, int skip_flag);
+void BKE_blendfile_read_make_empty(struct bContext *C);
+
+struct UserDef *BKE_blendfile_userdef_read(
+ const char *filepath, struct ReportList *reports);
+struct UserDef *BKE_blendfile_userdef_read_from_memory(
+ const void *filebuf, int filelength,
struct ReportList *reports);
-int BKE_blendfile_read_userdef(const char *filepath, struct ReportList *reports);
-int BKE_blendfile_write_userdef(const char *filepath, struct ReportList *reports);
+int BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports);
/* partial blend file writing */
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index bf45a27e51c..cb72f0859d5 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -54,7 +54,6 @@ typedef struct BVHTreeFromEditMesh {
/* default callbacks to bvh nearest and raycast */
BVHTree_NearestPointCallback nearest_callback;
BVHTree_RayCastCallback raycast_callback;
- BVHTree_NearestToRayCallback nearest_to_ray_callback;
struct BMEditMesh *em;
@@ -75,7 +74,6 @@ typedef struct BVHTreeFromMesh {
/* default callbacks to bvh nearest and raycast */
BVHTree_NearestPointCallback nearest_callback;
BVHTree_RayCastCallback raycast_callback;
- BVHTree_NearestToRayCallback nearest_to_ray_callback;
/* Vertex array, so that callbacks have instante access to data */
const struct MVert *vert;
@@ -104,7 +102,7 @@ typedef struct BVHTreeFromMesh {
* The tree is build in mesh space coordinates, this means special care must be made on queries
* so that the coordinates and rays are first translated on the mesh local coordinates.
* Reason for this is that bvh_from_mesh_* can use a cache in some cases and so it becomes possible to reuse a BVHTree.
- *
+ *
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
BVHTree *bvhtree_from_editmesh_verts(
@@ -118,7 +116,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
BVHTree *bvhtree_from_mesh_verts(
struct BVHTreeFromMesh *data, struct DerivedMesh *mesh, float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_verts_ex(
- struct BVHTreeFromMesh *data, struct MVert *vert, const int numVerts,
+ struct BVHTreeFromMesh *data, const struct MVert *vert, const int numVerts,
const bool vert_allocated, const BLI_bitmap *mask, int verts_num_active,
float epsilon, int tree_type, int axis);
@@ -135,8 +133,8 @@ BVHTree *bvhtree_from_mesh_edges(
float epsilon, int tree_type, int axis);
BVHTree *bvhtree_from_mesh_edges_ex(
struct BVHTreeFromMesh *data,
- struct MVert *vert, const bool vert_allocated,
- struct MEdge *edge, const int edges_num, const bool edge_allocated,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MEdge *edge, const int edges_num, const bool edge_allocated,
const BLI_bitmap *edges_mask, int edges_num_active,
float epsilon, int tree_type, int axis);
@@ -145,8 +143,8 @@ BVHTree *bvhtree_from_mesh_faces(
int tree_type, int axis);
BVHTree *bvhtree_from_mesh_faces_ex(
struct BVHTreeFromMesh *data,
- struct MVert *vert, const bool vert_allocated,
- struct MFace *face, const int numFaces, const bool face_allocated,
+ const struct MVert *vert, const bool vert_allocated,
+ const struct MFace *face, const int numFaces, const bool face_allocated,
const BLI_bitmap *mask, int numFaces_active,
float epsilon, int tree_type, int axis);
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 7e1c069df9a..0d4ed2083b1 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -55,7 +55,7 @@ void BKE_cachefile_reload(const struct Main *bmain, struct CacheFile *cache_file
void BKE_cachefile_ensure_handle(const struct Main *bmain, struct CacheFile *cache_file);
-void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene,const float ctime, const float fps);
+void BKE_cachefile_update_frame(struct Main *bmain, struct Scene *scene, const float ctime, const float fps);
bool BKE_cachefile_filepath_get(
const struct Main *bmain, const struct CacheFile *cache_file, float frame,
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index 31a732cf7e5..740a1f2b257 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -44,6 +44,7 @@ struct Object;
struct RegionView3D;
struct RenderData;
struct Scene;
+struct SceneLayer;
struct rctf;
struct View3D;
struct GPUFXSettings;
@@ -127,7 +128,7 @@ void BKE_camera_view_frame(
float r_vec[4][3]);
bool BKE_camera_view_frame_fit_to_scene(
- struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
+ struct Scene *scene, struct SceneLayer *sl, struct Object *camera_ob,
float r_co[3], float *r_scale);
bool BKE_camera_view_frame_fit_to_coords(
const struct Scene *scene,
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 36330242f18..6c517bd02df 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -136,9 +136,6 @@ typedef struct ClothSpring {
float restlen; /* The original length of the spring. */
int type; /* types defined in BKE_cloth.h ("springType") */
int flags; /* defined in BKE_cloth.h, e.g. deactivated due to tearing */
- float dfdx[3][3];
- float dfdv[3][3];
- float f[3];
float stiffness; /* stiffness factor from the vertex groups */
float editrestlen;
@@ -240,9 +237,6 @@ void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
// needed for button_object.c
void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr );
-// needed for cloth.c
-int cloth_add_spring (struct ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type);
-
void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]);
////////////////////////////////////////////////
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 90904cdfddd..17acba78ffa 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -44,12 +44,21 @@ struct Scene;
struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
-struct SceneCollection *BKE_collection_master(struct Scene *scene);
+struct SceneCollection *BKE_collection_master(const struct Scene *scene);
+void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name);
void BKE_collection_master_free(struct Scene *scene);
-void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add(const struct Scene *scene, struct SceneCollection *sc, struct Object *object);
void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
-void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
+void BKE_collection_object_remove(struct Main *bmain, const struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
+void BKE_collection_object_move(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob);
+
+void BKE_collection_reinsert_after(const struct Scene *scene, struct SceneCollection *sc_reinsert, struct SceneCollection *sc_after);
+void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct SceneCollection *sc_into);
+
+bool BKE_collection_move_above(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_below(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_into(const struct Scene *scene, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
@@ -66,20 +75,20 @@ void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in);
void BKE_scene_objects_Iterator_next(struct Iterator *iter);
void BKE_scene_objects_Iterator_end(struct Iterator *iter);
-#define FOREACH_SCENE_COLLECTION(scene, _sc) \
+#define FOREACH_SCENE_COLLECTION(scene, _instance) \
ITER_BEGIN(BKE_scene_collections_Iterator_begin, \
BKE_scene_collections_Iterator_next, \
BKE_scene_collections_Iterator_end, \
- scene, SceneCollection, _sc)
+ scene, SceneCollection *, _instance)
#define FOREACH_SCENE_COLLECTION_END \
ITER_END
-#define FOREACH_SCENE_OBJECT(scene, _ob) \
+#define FOREACH_SCENE_OBJECT(scene, _instance) \
ITER_BEGIN(BKE_scene_objects_Iterator_begin, \
BKE_scene_objects_Iterator_next, \
BKE_scene_objects_Iterator_end, \
- scene, Object, _ob)
+ scene, Object *, _instance)
#define FOREACH_SCENE_OBJECT_END \
ITER_END
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 23f9ff28f8b..22368104566 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,6 +40,7 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct Depsgraph;
struct LayerCollection;
struct ListBase;
struct Main;
@@ -170,7 +171,6 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C);
struct SpaceInfo *CTX_wm_space_info(const bContext *C);
struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
struct SpaceClip *CTX_wm_space_clip(const bContext *C);
-struct SpaceCollections *CTX_wm_space_collections(const bContext *C);
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
@@ -304,6 +304,7 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+struct Depsgraph *CTX_data_depsgraph(const bContext *C);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 5558786d254..e111bd0e16b 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -36,6 +36,7 @@
struct BezTriple;
struct Curve;
struct EditNurb;
+struct GHash;
struct ListBase;
struct Main;
struct Nurb;
@@ -52,6 +53,13 @@ typedef struct CurveCache {
struct Path *path;
} CurveCache;
+/* Definitions needed for shape keys */
+typedef struct CVKeyIndex {
+ void *orig_cv;
+ int key_index, nu_index, pt_index, vertex_index;
+ bool switched;
+} CVKeyIndex;
+
#define KNOTSU(nu) ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) )
#define KNOTSV(nu) ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) )
@@ -108,7 +116,8 @@ void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
-void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb);
+void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv);
+void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
index 40564aeabe9..93db48ce49a 100644
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ b/source/blender/blenkernel/BKE_depsgraph.h
@@ -44,6 +44,7 @@
extern "C" {
#endif
+struct Depsgraph;
struct ID;
struct Main;
struct Object;
@@ -174,6 +175,10 @@ const char *DAG_get_node_name(struct Scene *scene, void *node_v);
short DAG_get_eval_flags_for_object(struct Scene *scene, void *object);
bool DAG_is_acyclic(struct Scene *scene);
+/* ************************ DAG ********************* */
+
+struct Object *DAG_get_object(struct Depsgraph *depsgraph, struct Object *ob);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 9bee353bb3a..9e7155cf482 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): Dalai Felinto
+ * Contributor(s): Blender Foundation, Dalai Felinto
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -42,9 +42,12 @@ extern "C" {
#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */
#define TODO_LAYER /* generic todo */
-struct CollectionEngineSettings;
+#define ROOT_PROP "root"
+
+struct EvaluationContext;
struct LayerCollection;
struct ID;
+struct IDProperty;
struct ListBase;
struct Main;
struct Object;
@@ -54,7 +57,8 @@ struct Scene;
struct SceneCollection;
struct SceneLayer;
-struct SceneLayer *BKE_scene_layer_active(struct Scene *scene);
+struct SceneLayer *BKE_scene_layer_render_active(const struct Scene *scene);
+struct SceneLayer *BKE_scene_layer_context_active(struct Scene *scene);
struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
@@ -65,16 +69,10 @@ void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
-struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
+struct SceneLayer *BKE_scene_layer_find_from_collection(const struct Scene *scene, struct LayerCollection *lc);
struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
-void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
-
-void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl);
-void BKE_scene_layer_engine_settings_object_recalculate(struct SceneLayer *sl, struct Object *ob);
-void BKE_scene_layer_engine_settings_collection_recalculate(struct SceneLayer *sl, struct LayerCollection *lc);
-void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name);
void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
@@ -82,43 +80,61 @@ struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
int BKE_layer_collection_count(struct SceneLayer *sl);
-int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc);
+int BKE_layer_collection_findindex(struct SceneLayer *sl, const struct LayerCollection *lc);
+
+bool BKE_layer_collection_move_above(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_below(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_into(const struct Scene *scene, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+
+void BKE_layer_collection_resync(const struct Scene *scene, const struct SceneCollection *sc);
struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc);
void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
-bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, const struct SceneCollection *sc);
bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
/* syncing */
void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
-void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
-void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_link(const struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(const struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
/* override */
void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
/* engine settings */
-typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
-struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name);
+typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct IDProperty *props);
+struct IDProperty *BKE_layer_collection_engine_get(struct LayerCollection *lc, const int type, const char *engine_name);
+struct IDProperty *BKE_object_collection_engine_get(struct Object *ob, const int type, const char *engine_name);
void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func);
void BKE_layer_collection_engine_settings_callback_free(void);
-
-struct CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name);
-void BKE_layer_collection_engine_settings_free(struct CollectionEngineSettings *ces);
-
-void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value);
-void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value);
-struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name);
-int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name);
-float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name);
-void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value);
-void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value);
-bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name);
-void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value);
+void BKE_layer_collection_engine_settings_create(struct IDProperty *root);
+
+void BKE_collection_engine_property_add_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_add_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_add_bool(struct IDProperty *props, const char *name, bool value);
+
+int BKE_collection_engine_property_value_get_int(struct IDProperty *props, const char *name);
+float BKE_collection_engine_property_value_get_float(struct IDProperty *props, const char *name);
+bool BKE_collection_engine_property_value_get_bool(struct IDProperty *props, const char *name);
+void BKE_collection_engine_property_value_set_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_value_set_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, const char *name, bool value);
+
+/* evaluation */
+
+void BKE_layer_eval_layer_collection_pre(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct SceneLayer *scene_layer);
+void BKE_layer_eval_layer_collection(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct LayerCollection *layer_collection,
+ struct LayerCollection *parent_layer_collection);
+void BKE_layer_eval_layer_collection_post(struct EvaluationContext *eval_ctx,
+ struct SceneLayer *scene_layer);
/* iterators */
@@ -134,46 +150,47 @@ void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
void BKE_visible_bases_Iterator_next(Iterator *iter);
void BKE_visible_bases_Iterator_end(Iterator *iter);
-#define FOREACH_SELECTED_OBJECT(sl, _ob) \
+#define FOREACH_SELECTED_OBJECT(sl, _instance) \
ITER_BEGIN(BKE_selected_objects_Iterator_begin, \
BKE_selected_objects_Iterator_next, \
BKE_selected_objects_Iterator_end, \
- sl, Object, _ob)
+ sl, Object *, _instance)
#define FOREACH_SELECTED_OBJECT_END \
ITER_END
-#define FOREACH_VISIBLE_OBJECT(sl, _ob) \
+#define FOREACH_VISIBLE_OBJECT(sl, _instance) \
ITER_BEGIN(BKE_visible_objects_Iterator_begin, \
BKE_visible_objects_Iterator_next, \
BKE_visible_objects_Iterator_end, \
- sl, Object, _ob)
+ sl, Object *, _instance)
#define FOREACH_VISIBLE_OBJECT_END \
ITER_END
-#define FOREACH_VISIBLE_BASE(sl, _object_base) \
+#define FOREACH_VISIBLE_BASE(sl, _instance) \
ITER_BEGIN(BKE_visible_bases_Iterator_begin, \
BKE_visible_bases_Iterator_next, \
BKE_visible_bases_Iterator_end, \
- sl, Base, _object_base)
+ sl, Base *, _instance)
#define FOREACH_VISIBLE_BASE_END \
ITER_END
-#define FOREACH_OBJECT(sl, _ob) \
+#define FOREACH_OBJECT(sl, _instance) \
{ \
+ Object *_instance; \
Base *base; \
- for (base = sl->object_bases.first; base; base = base->next) { \
- _ob = base->object;
+ for (base = (sl)->object_bases.first; base; base = base->next) { \
+ _instance = base->object;
#define FOREACH_OBJECT_END \
} \
}
-#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \
+#define FOREACH_OBJECT_FLAG(scene, sl, flag, _instance) \
{ \
IteratorBeginCb func_begin; \
IteratorCb func_next, func_end; \
@@ -183,34 +200,35 @@ void BKE_visible_bases_Iterator_end(Iterator *iter);
func_begin = &BKE_selected_objects_Iterator_begin; \
func_next = &BKE_selected_objects_Iterator_next; \
func_end = &BKE_selected_objects_Iterator_end; \
- data_in = sl; \
- } \
+ data_in = (sl); \
+ } \
else { \
func_begin = BKE_scene_objects_Iterator_begin; \
func_next = BKE_scene_objects_Iterator_next; \
func_end = BKE_scene_objects_Iterator_end; \
- data_in = scene; \
- } \
- ITER_BEGIN(func_begin, func_next, func_end, data_in, Object, _ob)
+ data_in = (scene); \
+ } \
+ ITER_BEGIN(func_begin, func_next, func_end, data_in, Object *, _instance)
#define FOREACH_OBJECT_FLAG_END \
ITER_END \
}
-/* temporary hacky solution waiting for final depsgraph evaluation */
-#define DEG_OBJECT_ITER(sl_, engine_name_, ob_) \
+/* temporary hacky solution waiting for CoW depsgraph implementation */
+#define DEG_OBJECT_ITER(sl_, instance_) \
{ \
- /* temporary solution, waiting for depsgraph update */ \
- BKE_scene_layer_engine_settings_update(sl, engine_name_); \
- \
- /* flush all the data to objects*/ \
+ /* flush all the depsgraph data to objects */ \
+ Object *instance_; \
Base *base_; \
- for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \
- ob_ = base_->object; \
- ob_->base_flag = base_->flag;
+ for (base_ = (sl_)->object_bases.first; base_; base_ = base_->next) { \
+ if ((base_->flag & BASE_VISIBLED) != 0) { \
+ instance_ = base_->object; \
+ instance_->base_flag = base_->flag; \
+ instance_->base_collection_properties = base_->collection_properties;
#define DEG_OBJECT_ITER_END \
+ } \
} \
}
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index d41878825bb..b83bec5a302 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -131,8 +131,7 @@ bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const cha
float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
-void BKE_mesh_calc_normals_split(struct Mesh *mesh);
-void BKE_mesh_split_faces(struct Mesh *mesh);
+void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
@@ -228,6 +227,9 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space, const float
bool BKE_mesh_has_custom_loop_normals(struct Mesh *me);
+void BKE_mesh_calc_normals_split(struct Mesh *mesh);
+void BKE_mesh_calc_normals_split_ex(struct Mesh *mesh, struct MLoopNorSpaceArray *r_lnors_spacearr);
+
void BKE_mesh_normals_loop_split(
const struct MVert *mverts, const int numVerts, struct MEdge *medges, const int numEdges,
struct MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
diff --git a/source/blender/blenkernel/BKE_mesh_render.h b/source/blender/blenkernel/BKE_mesh_render.h
index 29787dcfdab..0869c96abf0 100644
--- a/source/blender/blenkernel/BKE_mesh_render.h
+++ b/source/blender/blenkernel/BKE_mesh_render.h
@@ -33,11 +33,18 @@ struct Batch;
struct Mesh;
void BKE_mesh_batch_cache_dirty(struct Mesh *me);
+void BKE_mesh_batch_selection_dirty(struct Mesh *me);
+void BKE_mesh_batch_cache_clear(struct Mesh *me);
void BKE_mesh_batch_cache_free(struct Mesh *me);
struct Batch *BKE_mesh_batch_cache_get_all_edges(struct Mesh *me);
struct Batch *BKE_mesh_batch_cache_get_all_triangles(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
struct Batch *BKE_mesh_batch_cache_get_all_verts(struct Mesh *me);
struct Batch *BKE_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
-struct Batch *BKE_mesh_batch_cache_get_overlay_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
+struct Batch *BKE_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);
#endif /* __BKE_MESH_RENDER_H__ */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 67f7fa5e029..7eb611d43a2 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -49,7 +49,7 @@
#include "RNA_types.h"
/* not very important, but the stack solver likes to know a maximum */
-#define MAX_SOCKET 64
+#define MAX_SOCKET 512
struct bContext;
struct bNode;
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 4dd9e01ba32..aa70d074d10 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -38,10 +38,10 @@ extern "C" {
struct BaseLegacy;
struct EvaluationContext;
struct Scene;
+struct SceneLayer;
struct Object;
struct BoundBox;
struct View3D;
-struct SceneLayer;
struct SoftBody;
struct BulletSoftBody;
struct MovieClip;
@@ -102,9 +102,9 @@ void BKE_object_lod_add(struct Object *ob);
void BKE_object_lod_sort(struct Object *ob);
bool BKE_object_lod_remove(struct Object *ob, int level);
void BKE_object_lod_update(struct Object *ob, const float camera_position[3]);
-bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
+bool BKE_object_lod_is_usable(struct Object *ob, struct SceneLayer *sl);
+struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct SceneLayer *sl);
+struct Object *BKE_object_lod_matob_get(struct Object *ob, struct SceneLayer *sl);
struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches);
struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob);
@@ -140,8 +140,6 @@ void BKE_boundbox_init_from_minmax(struct BoundBox *bb, const float min[3], cons
void BKE_boundbox_calc_center_aabb(const struct BoundBox *bb, float r_cent[3]);
void BKE_boundbox_calc_size_aabb(const struct BoundBox *bb, float r_size[3]);
void BKE_boundbox_minmax(const struct BoundBox *bb, float obmat[4][4], float r_min[3], float r_max[3]);
-struct BoundBox *BKE_boundbox_ensure_minimum_dimensions(
- struct BoundBox *bb, struct BoundBox *bb_temp, const float epsilon);
struct BoundBox *BKE_object_boundbox_get(struct Object *ob);
void BKE_object_dimensions_get(struct Object *ob, float vec[3]);
@@ -155,8 +153,7 @@ bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min
void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4],
void (*func_cb)(const float[3], void *), void *user_data);
void BKE_scene_foreach_display_point(struct Scene *scene,
- struct View3D *v3d,
- const short flag,
+ struct SceneLayer *sl,
void (*func_cb)(const float[3], void *), void *user_data);
bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
@@ -202,7 +199,11 @@ void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_shading(struct EvaluationContext *eval_ctx, struct Object *ob);
+
+void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *object);
+
void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
struct Scene *scene,
@@ -254,7 +255,7 @@ typedef enum eObjectSet {
OB_SET_ALL /* All Objects */
} eObjectSet;
-struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
+struct LinkNode *BKE_object_relational_superset(struct SceneLayer *scene_layer, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
void BKE_object_groups_clear(struct Object *object);
diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h
index 454edb40c4e..b82bc692402 100644
--- a/source/blender/blenkernel/BKE_outliner_treehash.h
+++ b/source/blender/blenkernel/BKE_outliner_treehash.h
@@ -36,8 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore)
/* full rebuild for already allocated hashtable */
void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
-/* full rebuild for already allocated hashtable */
+/* Add/remove hashtable elements */
void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
+void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem);
/* find first unused element with specific type, nr and id */
struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 0a3cc950f32..f72c4ad9dac 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -52,6 +52,7 @@ struct PaletteColor;
struct PBVH;
struct ReportList;
struct Scene;
+struct SceneLayer;
struct Sculpt;
struct StrokeCache;
struct Tex;
@@ -89,8 +90,8 @@ typedef enum OverlayControlFlags {
PAINT_OVERLAY_OVERRIDE_PRIMARY | \
PAINT_OVERLAY_OVERRIDE_CURSOR)
-void BKE_paint_invalidate_overlay_tex(struct Scene *scene, const struct Tex *tex);
-void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct CurveMapping *curve);
+void BKE_paint_invalidate_overlay_tex(struct Scene *scene, struct SceneLayer *sl, const struct Tex *tex);
+void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct SceneLayer *sl, struct CurveMapping *curve);
void BKE_paint_invalidate_overlay_all(void);
OverlayControlFlags BKE_paint_get_overlay_flags(void);
void BKE_paint_reset_overlay_invalid(OverlayControlFlags flag);
@@ -120,7 +121,7 @@ void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
short BKE_paint_object_mode_from_paint_mode(PaintMode mode);
struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, PaintMode mode);
-struct Paint *BKE_paint_get_active(struct Scene *sce);
+struct Paint *BKE_paint_get_active(struct Scene *sce, struct SceneLayer *sl);
struct Paint *BKE_paint_get_active_from_context(const struct bContext *C);
PaintMode BKE_paintmode_get_active_from_context(const struct bContext *C);
struct Brush *BKE_paint_brush(struct Paint *paint);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index e5967be0bc7..2b6a84a2f87 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -207,7 +207,7 @@ typedef struct ParticleCollisionElement {
typedef struct ParticleCollision {
struct Object *current;
struct Object *hit;
- struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS+1];
+ struct Object *skip[PARTICLE_COLLISION_MAX_COLLISIONS + 1];
struct Object *emitter;
struct CollisionModifierData *md; // collision modifier for current object;
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 181d4b12703..0e264c5a125 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -47,6 +47,7 @@ struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
struct Scene;
+struct SceneCollection;
struct SceneLayer;
struct UnitSettings;
struct Main;
@@ -63,7 +64,7 @@ struct Main;
_base; \
_base = _setlooper_base_step(&_sce_iter, _base)
-struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base);
+struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
@@ -111,6 +112,8 @@ void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local);
+struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct SceneCollection *scene_collection);
+
struct Object *BKE_scene_camera_find(struct Scene *sc);
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 811e9136fc9..7c09cafaf64 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -421,7 +421,7 @@ struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seq
/* view3d draw callback, run when not in background view */
typedef struct ImBuf *(*SequencerDrawView)(
- struct Scene *, struct Object *, int, int,
+ struct Scene *, struct SceneLayer *sl, struct Object *, int, int,
unsigned int, int, bool, bool, bool,
int, int, bool, const char *,
struct GPUFX *, struct GPUOffScreen *, char[256]);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 6202c84f320..b665183a37b 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenloader
../blentranslation
../depsgraph
+ ../draw
../gpu
../ikplugin
../imbuf
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 39f1db0b886..b9cc9540cf7 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -76,8 +76,8 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
#include "GPU_buffers.h"
-#include "GPU_glew.h"
#include "GPU_shader.h"
+#include "GPU_immediate.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_depsgraph.h"
@@ -2913,9 +2913,6 @@ DerivedMesh *editbmesh_get_derived_base(Object *obedit, BMEditMesh *em, CustomDa
/* get derived mesh from an object, using editbmesh if available. */
DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
{
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_btmesh;
-
if (for_render) {
/* TODO(sergey): use proper derived render here in the future. */
return ob->derivedFinal;
@@ -2923,9 +2920,13 @@ DerivedMesh *object_get_derived_final(Object *ob, const bool for_render)
/* only return the editmesh if its from this object because
* we don't a mesh from another object's modifier stack: T43122 */
- if (em && (em->ob == ob)) {
- DerivedMesh *dm = em->derivedFinal;
- return dm;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em && (em->ob == ob)) {
+ DerivedMesh *dm = em->derivedFinal;
+ return dm;
+ }
}
return ob->derivedFinal;
@@ -3937,7 +3938,6 @@ BLI_INLINE void navmesh_intToCol(int i, float col[3])
static void navmesh_drawColored(DerivedMesh *dm)
{
- int a, glmode;
MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
int *polygonIdx = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST);
@@ -3952,34 +3952,42 @@ static void navmesh_drawColored(DerivedMesh *dm)
dm->drawEdges(dm, 0, 1);
#endif
- /* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
- {
- DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
- glBegin(glmode = GL_QUADS);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- int new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
- int pi = polygonIdx[a];
- if (pi <= 0) {
- zero_v3(col);
- }
- else {
- navmesh_intToCol(pi, col);
- }
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", COMP_F32, 3, KEEP_FLOAT);
- if (new_glmode != glmode) {
- glEnd();
- glBegin(glmode = new_glmode);
- }
- glColor3fv(col);
- glVertex3fv(mvert[mface->v1].co);
- glVertex3fv(mvert[mface->v2].co);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glVertex3fv(mvert[mface->v4].co);
- }
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* Note: batch drawing API would let us share vertices */
+ immBeginAtMost(PRIM_TRIANGLES, dm->numTessFaceData * 6);
+ for (int a = 0; a < dm->numTessFaceData; a++, mface++) {
+ int pi = polygonIdx[a];
+ if (pi <= 0) {
+ zero_v3(col);
+ }
+ else {
+ navmesh_intToCol(pi, col);
+ }
+
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v2].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v3].co);
+
+ if (mface->v4) {
+ /* this tess face is a quad, so draw the other triangle */
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v3].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v4].co);
}
- glEnd();
}
+ immEnd();
+ immUnbindProgram();
}
static void navmesh_DM_drawFacesTex(
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index b1dcc40279f..43fd47981b1 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -114,18 +114,26 @@ static char *blender_version_decimal(const int ver)
* Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
* returning true if result points to a directory.
*/
-static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
+static bool test_path(
+ char *targetpath, size_t targetpath_len,
+ const char *path_base, const char *path_sep, const char *folder_name)
{
char tmppath[FILE_MAX];
- if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
- else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
-
- /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
- if (folder_name)
- BLI_make_file_string("/", targetpath, tmppath, folder_name);
- else
- BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
+ if (path_sep) {
+ BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
+ }
+ else {
+ BLI_strncpy(tmppath, path_base, sizeof(tmppath));
+ }
+
+ /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */
+ if (folder_name) {
+ BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name);
+ }
+ else {
+ BLI_strncpy(targetpath, tmppath, targetpath_len);
+ }
/* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
* if folder_name is specified but not otherwise? */
@@ -179,7 +187,9 @@ static bool test_env_path(char *path, const char *envvar)
* \param ver To construct name of version-specific directory within bprogdir
* \return true if such a directory exists.
*/
-static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
+static bool get_path_local(
+ char *targetpath, size_t targetpath_len,
+ const char *folder_name, const char *subfolder_name, const int ver)
{
char relfolder[FILE_MAX];
@@ -201,11 +211,12 @@ static bool get_path_local(char *targetpath, const char *folder_name, const char
/* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
#ifdef __APPLE__
- static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
+ static char osx_resourses[FILE_MAX];
sprintf(osx_resourses, "%s../Resources", bprogdir);
- return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder);
+ return test_path(targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder);
#else
- return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder);
+ return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder);
#endif
}
@@ -219,7 +230,7 @@ static bool is_portable_install(void)
const int ver = BLENDER_VERSION;
char path[FILE_MAX];
- return get_path_local(path, "config", NULL, ver);
+ return get_path_local(path, sizeof(path), "config", NULL, ver);
}
/**
@@ -233,20 +244,22 @@ static bool is_portable_install(void)
* \param ver Blender version, used to construct a subdirectory name
* \return true if it was able to construct such a path.
*/
-static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+static bool get_path_user(
+ char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name,
+ const char *envvar, const int ver)
{
char user_path[FILE_MAX];
const char *user_base_path;
/* for portable install, user path is always local */
- if (is_portable_install())
- return get_path_local(targetpath, folder_name, subfolder_name, ver);
-
+ if (is_portable_install()) {
+ return get_path_local(targetpath, targetpath_len, folder_name, subfolder_name, ver);
+ }
user_path[0] = '\0';
if (test_env_path(user_path, envvar)) {
if (subfolder_name) {
- return test_path(targetpath, user_path, NULL, subfolder_name);
+ return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name);
}
else {
BLI_strncpy(targetpath, user_path, FILE_MAX);
@@ -266,10 +279,10 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char
#endif
if (subfolder_name) {
- return test_path(targetpath, user_path, folder_name, subfolder_name);
+ return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name);
}
else {
- return test_path(targetpath, user_path, NULL, folder_name);
+ return test_path(targetpath, targetpath_len, user_path, NULL, folder_name);
}
}
@@ -283,7 +296,9 @@ static bool get_path_user(char *targetpath, const char *folder_name, const char
* \param ver Blender version, used to construct a subdirectory name
* \return true if it was able to construct such a path.
*/
-static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
+static bool get_path_system(
+ char *targetpath, size_t targetpath_len, const char *folder_name, const char *subfolder_name,
+ const char *envvar, const int ver)
{
char system_path[FILE_MAX];
const char *system_base_path;
@@ -307,13 +322,13 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
/* try CWD/release/folder_name */
if (BLI_current_working_dir(cwd, sizeof(cwd))) {
- if (test_path(targetpath, cwd, "release", relfolder)) {
+ if (test_path(targetpath, targetpath_len, cwd, "release", relfolder)) {
return true;
}
}
/* try EXECUTABLE_DIR/release/folder_name */
- if (test_path(targetpath, bprogdir, "release", relfolder))
+ if (test_path(targetpath, targetpath_len, bprogdir, "release", relfolder))
return true;
/* end developer overrides */
@@ -324,7 +339,7 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
if (test_env_path(system_path, envvar)) {
if (subfolder_name) {
- return test_path(targetpath, system_path, NULL, subfolder_name);
+ return test_path(targetpath, targetpath_len, system_path, NULL, subfolder_name);
}
else {
BLI_strncpy(targetpath, system_path, FILE_MAX);
@@ -345,57 +360,63 @@ static bool get_path_system(char *targetpath, const char *folder_name, const cha
if (subfolder_name) {
/* try $BLENDERPATH/folder_name/subfolder_name */
- return test_path(targetpath, system_path, folder_name, subfolder_name);
+ return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name);
}
else {
/* try $BLENDERPATH/folder_name */
- return test_path(targetpath, system_path, NULL, folder_name);
+ return test_path(targetpath, targetpath_len, system_path, NULL, folder_name);
}
}
-/* get a folder out of the 'folder_id' presets for paths */
-/* returns the path if found, NULL string if not */
-const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
+/**
+ * Get a folder out of the 'folder_id' presets for paths.
+ * returns the path if found, NULL string if not
+ *
+ * \param subfolder: The name of a directory to check for,
+ * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir.
+ */
+const char *BKE_appdir_folder_id_ex(
+ const int folder_id, const char *subfolder,
+ char *path, size_t path_len)
{
const int ver = BLENDER_VERSION;
- static char path[FILE_MAX] = "";
-
+
switch (folder_id) {
case BLENDER_DATAFILES: /* general case */
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_DATAFILES:
- if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
return NULL;
case BLENDER_SYSTEM_DATAFILES:
- if (get_path_local(path, "datafiles", subfolder, ver)) break;
- if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
+ if (get_path_local(path, path_len, "datafiles", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_AUTOSAVE:
- if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
+ if (get_path_user(path, path_len, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
return NULL;
case BLENDER_USER_CONFIG:
- if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
+ if (get_path_user(path, path_len, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
return NULL;
case BLENDER_USER_SCRIPTS:
- if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
+ if (get_path_user(path, path_len, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
return NULL;
case BLENDER_SYSTEM_SCRIPTS:
- if (get_path_local(path, "scripts", subfolder, ver)) break;
- if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
+ if (get_path_local(path, path_len, "scripts", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
return NULL;
case BLENDER_SYSTEM_PYTHON:
- if (get_path_local(path, "python", subfolder, ver)) break;
- if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
+ if (get_path_local(path, path_len, "python", subfolder, ver)) break;
+ if (get_path_system(path, path_len, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
return NULL;
default:
@@ -406,6 +427,13 @@ const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
return path;
}
+const char *BKE_appdir_folder_id(
+ const int folder_id, const char *subfolder)
+{
+ static char path[FILE_MAX] = "";
+ return BKE_appdir_folder_id_ex(folder_id, subfolder, path, sizeof(path));
+}
+
/**
* Returns the path to a folder in the user area without checking that it actually exists first.
*/
@@ -416,16 +444,16 @@ const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *su
switch (folder_id) {
case BLENDER_USER_DATAFILES:
- get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
+ get_path_user(path, sizeof(path), "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
break;
case BLENDER_USER_CONFIG:
- get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
+ get_path_user(path, sizeof(path), "config", subfolder, "BLENDER_USER_CONFIG", ver);
break;
case BLENDER_USER_AUTOSAVE:
- get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
+ get_path_user(path, sizeof(path), "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
break;
case BLENDER_USER_SCRIPTS:
- get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
+ get_path_user(path, sizeof(path), "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
break;
default:
BLI_assert(0);
@@ -469,13 +497,13 @@ const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, con
bool ok;
switch (folder_id) {
case BLENDER_RESOURCE_PATH_USER:
- ok = get_path_user(path, NULL, NULL, NULL, ver);
+ ok = get_path_user(path, sizeof(path), NULL, NULL, NULL, ver);
break;
case BLENDER_RESOURCE_PATH_LOCAL:
- ok = get_path_local(path, NULL, NULL, ver);
+ ok = get_path_local(path, sizeof(path), NULL, NULL, ver);
break;
case BLENDER_RESOURCE_PATH_SYSTEM:
- ok = get_path_system(path, NULL, NULL, NULL, ver);
+ ok = get_path_system(path, sizeof(path), NULL, NULL, NULL, ver);
break;
default:
path[0] = '\0'; /* in case do_check is false */
@@ -655,6 +683,48 @@ bool BKE_appdir_program_python_search(
return is_found;
}
+static const char *app_template_directory_search[2] = {
+ "startup" SEP_STR "bl_app_templates_user",
+ "startup" SEP_STR "bl_app_templates_system",
+};
+
+static const int app_template_directory_id[2] = {
+ BLENDER_USER_SCRIPTS,
+ BLENDER_SYSTEM_SCRIPTS,
+};
+
+/**
+ * Return true if templates exist
+ */
+bool BKE_appdir_app_template_any(void)
+{
+ char temp_dir[FILE_MAX];
+ for (int i = 0; i < 2; i++) {
+ if (BKE_appdir_folder_id_ex(
+ app_template_directory_id[i], app_template_directory_search[i],
+ temp_dir, sizeof(temp_dir)))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len)
+{
+ for (int i = 0; i < 2; i++) {
+ char subdir[FILE_MAX];
+ BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template);
+ if (BKE_appdir_folder_id_ex(
+ app_template_directory_id[i], subdir,
+ path, path_len))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Gets the temp directory when blender first runs.
* If the default path is not found, use try $TEMP
@@ -713,7 +783,8 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c
BLI_add_slash(fullname);
#ifdef WIN32
if (userdir && userdir != fullname) {
- BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
+ BLI_strncpy(userdir, fullname, maxlen);
}
#endif
}
@@ -755,7 +826,6 @@ static void where_is_temp(char *fullname, char *basename, const size_t maxlen, c
void BKE_tempdir_init(char *userdir)
{
where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
-;
}
/**
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index afd60102453..ceb641073e0 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -100,6 +100,18 @@ void BKE_blender_free(void)
free_nodesystem();
}
+void BKE_blender_version_string(char *version_str, size_t maxncpy, short version, short subversion, bool v_prefix, bool include_subversion)
+{
+ const char *prefix = v_prefix ? "v" : "";
+
+ if (include_subversion && subversion > 0) {
+ BLI_snprintf(version_str, maxncpy, "%s%d.%02d.%d", prefix, version / 100, version % 100, subversion);
+ }
+ else {
+ BLI_snprintf(version_str, maxncpy, "%s%d.%02d", prefix, version / 100, version % 100);
+ }
+}
+
void BKE_blender_globals_init(void)
{
memset(&G, 0, sizeof(Global));
@@ -110,10 +122,7 @@ void BKE_blender_globals_init(void)
strcpy(G.ima, "//");
- if (BLENDER_SUBVERSION)
- BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d.%d", BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION);
- else
- BLI_snprintf(versionstr, sizeof(versionstr), "v%d.%02d", BLENDER_VERSION / 100, BLENDER_VERSION % 100);
+ BKE_blender_version_string(versionstr, sizeof(versionstr), BLENDER_VERSION, BLENDER_SUBVERSION, true, true);
#ifndef WITH_PYTHON_SECURITY /* default */
G.f |= G_SCRIPT_AUTOEXEC;
@@ -141,20 +150,18 @@ static void keymap_item_free(wmKeyMapItem *kmi)
MEM_freeN(kmi->ptr);
}
-/**
- * When loading a new userdef from file,
- * or when exiting Blender.
- */
-void BKE_blender_userdef_free(void)
+void BKE_blender_userdef_set_data(UserDef *userdef)
{
- wmKeyMap *km;
- wmKeyMapItem *kmi;
- wmKeyMapDiffItem *kmdi;
- bAddon *addon, *addon_next;
- uiFont *font;
-
- for (km = U.user_keymaps.first; km; km = km->next) {
- for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
+ /* only here free userdef themes... */
+ BKE_blender_userdef_free_data(&U);
+ U = *userdef;
+}
+
+static void userdef_free_keymaps(UserDef *userdef)
+{
+ for (wmKeyMap *km = userdef->user_keymaps.first, *km_next; km; km = km_next) {
+ km_next = km->next;
+ for (wmKeyMapDiffItem *kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
if (kmdi->add_item) {
keymap_item_free(kmdi->add_item);
MEM_freeN(kmdi->add_item);
@@ -165,14 +172,21 @@ void BKE_blender_userdef_free(void)
}
}
- for (kmi = km->items.first; kmi; kmi = kmi->next)
+ for (wmKeyMapItem *kmi = km->items.first; kmi; kmi = kmi->next) {
keymap_item_free(kmi);
+ }
BLI_freelistN(&km->diff_items);
BLI_freelistN(&km->items);
+
+ MEM_freeN(km);
}
-
- for (addon = U.addons.first; addon; addon = addon_next) {
+ BLI_listbase_clear(&userdef->user_keymaps);
+}
+
+static void userdef_free_addons(UserDef *userdef)
+{
+ for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) {
addon_next = addon->next;
if (addon->prop) {
IDP_FreeProperty(addon->prop);
@@ -180,19 +194,35 @@ void BKE_blender_userdef_free(void)
}
MEM_freeN(addon);
}
+ BLI_listbase_clear(&userdef->addons);
+}
- for (font = U.uifonts.first; font; font = font->next) {
+/**
+ * When loading a new userdef from file,
+ * or when exiting Blender.
+ */
+void BKE_blender_userdef_free_data(UserDef *userdef)
+{
+#define U _invalid_access_ /* ensure no accidental global access */
+#ifdef U /* quiet warning */
+#endif
+
+ userdef_free_keymaps(userdef);
+ userdef_free_addons(userdef);
+
+ for (uiFont *font = userdef->uifonts.first; font; font = font->next) {
BLF_unload_id(font->blf_id);
}
BLF_default_set(-1);
- BLI_freelistN(&U.autoexec_paths);
+ BLI_freelistN(&userdef->autoexec_paths);
+
+ BLI_freelistN(&userdef->uistyles);
+ BLI_freelistN(&userdef->uifonts);
+ BLI_freelistN(&userdef->themes);
- BLI_freelistN(&U.uistyles);
- BLI_freelistN(&U.uifonts);
- BLI_freelistN(&U.themes);
- BLI_freelistN(&U.user_keymaps);
+#undef U
}
/**
@@ -208,6 +238,44 @@ void BKE_blender_userdef_refresh(void)
}
+/**
+ * Write U from userdef.
+ * This function defines which settings a template will override for the user preferences.
+ */
+void BKE_blender_userdef_set_app_template(UserDef *userdef)
+{
+ /* TODO:
+ * - keymaps
+ * - various minor settings (add as needed).
+ */
+
+#define LIST_OVERRIDE(id) { \
+ BLI_freelistN(&U.id); \
+ BLI_movelisttolist(&U.id, &userdef->id); \
+} ((void)0)
+
+#define MEMCPY_OVERRIDE(id) \
+ memcpy(U.id, userdef->id, sizeof(U.id));
+
+ /* for some types we need custom free functions */
+ userdef_free_addons(&U);
+ userdef_free_keymaps(&U);
+
+ LIST_OVERRIDE(uistyles);
+ LIST_OVERRIDE(uifonts);
+ LIST_OVERRIDE(themes);
+ LIST_OVERRIDE(addons);
+ LIST_OVERRIDE(user_keymaps);
+
+ MEMCPY_OVERRIDE(light);
+
+ MEMCPY_OVERRIDE(font_path_ui);
+ MEMCPY_OVERRIDE(font_path_ui_mono);
+
+#undef LIST_OVERRIDE
+#undef MEMCPY_OVERRIDE
+}
+
/* ***************** testing for break ************* */
static void (*blender_test_break_cb)(void) = NULL;
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index bc98d6f6805..e3a5edb2049 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -108,9 +108,9 @@ static int read_undosave(bContext *C, UndoElem *uel)
G.fileflags |= G_FILE_NO_UI;
if (UNDO_DISK)
- success = (BKE_blendfile_read(C, uel->str, NULL) != BKE_BLENDFILE_READ_FAIL);
+ success = (BKE_blendfile_read(C, uel->str, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
else
- success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL);
+ success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL, 0);
/* restore */
BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
@@ -389,7 +389,7 @@ bool BKE_undo_save_file(const char *filename)
Main *BKE_undo_get_main(Scene **r_scene)
{
Main *mainp = NULL;
- BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL);
+ BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL, BLO_READ_SKIP_NONE);
if (bfd) {
mainp = bfd->main;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 54f709a1e5b..a521d671ea4 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -227,7 +227,7 @@ static void setup_app_data(
if (bfd->user) {
/* only here free userdef themes... */
- BKE_blender_userdef_free();
+ BKE_blender_userdef_free_data(&U);
U = *bfd->user;
@@ -349,17 +349,23 @@ static int handle_subversion_warning(Main *main, ReportList *reports)
return 1;
}
-int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports)
+int BKE_blendfile_read(
+ bContext *C, const char *filepath,
+ ReportList *reports, int skip_flags)
{
BlendFileData *bfd;
int retval = BKE_BLENDFILE_READ_OK;
- if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */
- printf("read blend: %s\n", filepath);
+ /* don't print user-pref loading */
+ if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) {
+ printf("Read blend: %s\n", filepath);
+ }
- bfd = BLO_read_from_file(filepath, reports);
+ bfd = BLO_read_from_file(filepath, reports, skip_flags);
if (bfd) {
- if (bfd->user) retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ if (bfd->user) {
+ retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ }
if (0 == handle_subversion_warning(bfd->main, reports)) {
BKE_main_free(bfd->main);
@@ -379,11 +385,11 @@ int BKE_blendfile_read(bContext *C, const char *filepath, ReportList *reports)
bool BKE_blendfile_read_from_memory(
bContext *C, const void *filebuf, int filelength,
- ReportList *reports, bool update_defaults)
+ ReportList *reports, int skip_flags, bool update_defaults)
{
BlendFileData *bfd;
- bfd = BLO_read_from_memory(filebuf, filelength, reports);
+ bfd = BLO_read_from_memory(filebuf, filelength, reports, skip_flags);
if (bfd) {
if (update_defaults)
BLO_update_defaults_startup_blend(bfd->main);
@@ -399,11 +405,11 @@ bool BKE_blendfile_read_from_memory(
/* memfile is the undo buffer */
bool BKE_blendfile_read_from_memfile(
bContext *C, struct MemFile *memfile,
- ReportList *reports)
+ ReportList *reports, int skip_flags)
{
BlendFileData *bfd;
- bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports);
+ bfd = BLO_read_from_memfile(CTX_data_main(C), G.main->name, memfile, reports, skip_flags);
if (bfd) {
/* remove the unused screens and wm */
while (bfd->main->wm.first)
@@ -420,32 +426,76 @@ bool BKE_blendfile_read_from_memfile(
return (bfd != NULL);
}
+/**
+ * Utility to make a file 'empty' used for startup to optionally give an empty file.
+ * Handy for tests.
+ */
+void BKE_blendfile_read_make_empty(bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+
+ ListBase *lbarray[MAX_LIBARRAY];
+ ID *id;
+ int a;
+
+ a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ id = lbarray[a]->first;
+ if (id != NULL) {
+ if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM)) {
+ continue;
+ }
+ while ((id = lbarray[a]->first)) {
+ BKE_libblock_delete(bmain, id);
+ }
+ }
+ }
+}
+
/* only read the userdef from a .blend */
-int BKE_blendfile_read_userdef(const char *filepath, ReportList *reports)
+UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports)
{
BlendFileData *bfd;
- int retval = BKE_BLENDFILE_READ_FAIL;
+ UserDef *userdef = NULL;
- bfd = BLO_read_from_file(filepath, reports);
+ bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF);
if (bfd) {
if (bfd->user) {
- retval = BKE_BLENDFILE_READ_OK_USERPREFS;
+ userdef = bfd->user;
+ }
+ BKE_main_free(bfd->main);
+ MEM_freeN(bfd);
+ }
- /* only here free userdef themes... */
- BKE_blender_userdef_free();
+ return userdef;
+}
- U = *bfd->user;
- MEM_freeN(bfd->user);
+
+UserDef *BKE_blendfile_userdef_read_from_memory(
+ const void *filebuf, int filelength,
+ ReportList *reports)
+{
+ BlendFileData *bfd;
+ UserDef *userdef = NULL;
+
+ bfd = BLO_read_from_memory(filebuf, filelength, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF);
+ if (bfd) {
+ if (bfd->user) {
+ userdef = bfd->user;
}
BKE_main_free(bfd->main);
MEM_freeN(bfd);
}
+ else {
+ BKE_reports_prepend(reports, "Loading failed: ");
+ }
- return retval;
+ return userdef;
}
+
/* only write the userdef in a .blend */
-int BKE_blendfile_write_userdef(const char *filepath, ReportList *reports)
+int BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
Main *mainb = MEM_callocN(sizeof(Main), "empty main");
int retval = 0;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index d0e0c82e3be..c0e4ef37a93 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -376,45 +376,6 @@ static void mesh_edges_spherecast(void *userdata, int index, const BVHTreeRay *r
}
}
-#define V3_MUL_ELEM(a, b) \
- (a)[0] * (b)[0], \
- (a)[1] * (b)[1], \
- (a)[2] * (b)[2]
-
-/* Callback to bvh tree nearest edge to ray.
- * The tree must have been built using bvhtree_from_mesh_edges.
- * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
-static void mesh_edges_nearest_to_ray(
- void *userdata, const float ray_co[3], const float ray_dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest)
-{
- struct BVHTreeFromMesh *data = userdata;
- const MVert *vert = data->vert;
- const MEdge *e = &data->edge[index];
-
- const float t0[3] = {V3_MUL_ELEM(vert[e->v1].co, scale)};
- const float t1[3] = {V3_MUL_ELEM(vert[e->v2].co, scale)};
- const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)};
- const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)};
-
- float depth, point[3];
- const float dist_sq = dist_squared_ray_to_seg_v3(origin_sc, dir_sc, t0, t1, point, &depth);
-
- if (dist_sq < nearest->dist_sq) {
- nearest->dist_sq = dist_sq;
- nearest->index = index;
-
- point[0] /= scale[0];
- point[1] /= scale[1];
- point[2] /= scale[2];
-
- copy_v3_v3(nearest->co, point);
- sub_v3_v3v3(nearest->no, t0, t1);
- }
-}
-
-#undef V3_MUL_ELEM
-
/** \} */
/*
@@ -459,7 +420,7 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
static BVHTree *bvhtree_from_mesh_verts_create_tree(
float epsilon, int tree_type, int axis,
- MVert *vert, const int verts_num,
+ const MVert *vert, const int verts_num,
const BLI_bitmap *verts_mask, int verts_num_active)
{
BLI_assert(vert != NULL);
@@ -488,31 +449,23 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(
static void bvhtree_from_mesh_verts_setup_data(
BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
- MVert *vert, const bool vert_allocated)
+ const MVert *vert, const bool vert_allocated)
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- /* a NULL nearest callback works fine
- * remember the min distance to point is the same as the min distance to BV of point */
- data->nearest_callback = NULL;
- data->raycast_callback = mesh_verts_spherecast;
- data->nearest_to_ray_callback = NULL;
+ /* a NULL nearest callback works fine
+ * remember the min distance to point is the same as the min distance to BV of point */
+ data->nearest_callback = NULL;
+ data->raycast_callback = mesh_verts_spherecast;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ //data->face = DM_get_tessface_array(dm, &data->face_allocated); /* XXX WHY???? */
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- }
+ data->sphere_radius = epsilon;
}
/* Builds a bvh tree where nodes are the vertices of the given em */
@@ -531,7 +484,6 @@ BVHTree *bvhtree_from_editmesh_verts_ex(
data->em = em;
data->nearest_callback = NULL;
data->raycast_callback = editmesh_verts_spherecast;
- data->nearest_to_ray_callback = NULL;
}
return tree;
@@ -588,11 +540,18 @@ BVHTree *bvhtree_from_mesh_verts(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(
- data, tree, true, epsilon, vert, vert_allocated);
-
- return data->tree;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ memset(data, 0, sizeof(*data));
+ }
+ return tree;
}
/**
@@ -602,7 +561,7 @@ BVHTree *bvhtree_from_mesh_verts(
* \param verts_num_active if >= 0, number of active verts to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_verts_ex(
- BVHTreeFromMesh *data, MVert *vert, const int verts_num, const bool vert_allocated,
+ BVHTreeFromMesh *data, const MVert *vert, const int verts_num, const bool vert_allocated,
const BLI_bitmap *verts_mask, int verts_num_active,
float epsilon, int tree_type, int axis)
{
@@ -613,7 +572,7 @@ BVHTree *bvhtree_from_mesh_verts_ex(
bvhtree_from_mesh_verts_setup_data(
data, tree, false, epsilon, vert, vert_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -661,7 +620,7 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
}
static BVHTree *bvhtree_from_mesh_edges_create_tree(
- MVert *vert, MEdge *edge, const int edge_num,
+ const MVert *vert, const MEdge *edge, const int edge_num,
const BLI_bitmap *edges_mask, int edges_num_active,
float epsilon, int tree_type, int axis)
{
@@ -694,34 +653,26 @@ static BVHTree *bvhtree_from_mesh_edges_create_tree(
}
static void bvhtree_from_mesh_edges_setup_data(
- BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
- MVert *vert, const bool vert_allocated, MEdge *edge, const bool edge_allocated)
+ BVHTreeFromMesh *data, BVHTree *tree,
+ const bool is_cached, float epsilon,
+ const MVert *vert, const bool vert_allocated,
+ const MEdge *edge, const bool edge_allocated)
{
memset(data, 0, sizeof(*data));
+
data->tree = tree;
- if (data->tree) {
- data->cached = is_cached;
+ data->cached = is_cached;
- data->nearest_callback = mesh_edges_nearest_point;
- data->raycast_callback = mesh_edges_spherecast;
- data->nearest_to_ray_callback = mesh_edges_nearest_to_ray;
+ data->nearest_callback = mesh_edges_nearest_point;
+ data->raycast_callback = mesh_edges_spherecast;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->edge = edge;
- data->edge_allocated = edge_allocated;
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->edge = edge;
+ data->edge_allocated = edge_allocated;
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (edge_allocated) {
- MEM_freeN(edge);
- }
- }
+ data->sphere_radius = epsilon;
}
/* Builds a bvh tree where nodes are the edges of the given em */
@@ -742,8 +693,6 @@ BVHTree *bvhtree_from_editmesh_edges_ex(
data->em = em;
data->nearest_callback = NULL; /* TODO */
data->raycast_callback = NULL; /* TODO */
- /* TODO: not urgent however since users currently define own callbacks */
- data->nearest_to_ray_callback = NULL;
}
return tree;
@@ -795,11 +744,21 @@ BVHTree *bvhtree_from_mesh_edges(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_edges_setup_data(
- data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated);
-
- return data->tree;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated, edge, edge_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (edge_allocated) {
+ MEM_freeN(edge);
+ }
+ memset(data, 0, sizeof(*data));
+ }
+ return tree;
}
/**
@@ -810,8 +769,8 @@ BVHTree *bvhtree_from_mesh_edges(
*/
BVHTree *bvhtree_from_mesh_edges_ex(
BVHTreeFromMesh *data,
- MVert *vert, const bool vert_allocated,
- MEdge *edge, const int edges_num, const bool edge_allocated,
+ const MVert *vert, const bool vert_allocated,
+ const MEdge *edge, const int edges_num, const bool edge_allocated,
const BLI_bitmap *edges_mask, int edges_num_active,
float epsilon, int tree_type, int axis)
{
@@ -823,7 +782,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(
bvhtree_from_mesh_edges_setup_data(
data, tree, false, epsilon, vert, vert_allocated, edge, edge_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -836,7 +795,7 @@ BVHTree *bvhtree_from_mesh_edges_ex(
static BVHTree *bvhtree_from_mesh_faces_create_tree(
float epsilon, int tree_type, int axis,
- MVert *vert, MFace *face, const int faces_num,
+ const MVert *vert, const MFace *face, const int faces_num,
const BLI_bitmap *faces_mask, int faces_num_active)
{
BVHTree *tree = NULL;
@@ -880,34 +839,23 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
static void bvhtree_from_mesh_faces_setup_data(
BVHTreeFromMesh *data, BVHTree *tree, const bool is_cached, float epsilon,
- MVert *vert, const bool vert_allocated,
- MFace *face, const bool face_allocated)
+ const MVert *vert, const bool vert_allocated,
+ const MFace *face, const bool face_allocated)
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- data->nearest_callback = mesh_faces_nearest_point;
- data->raycast_callback = mesh_faces_spherecast;
- data->nearest_to_ray_callback = NULL;
+ data->nearest_callback = mesh_faces_nearest_point;
+ data->raycast_callback = mesh_faces_spherecast;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->face = face;
- data->face_allocated = face_allocated;
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->face = face;
+ data->face_allocated = face_allocated;
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN(vert);
- }
- if (face_allocated) {
- MEM_freeN(face);
- }
- }
+ data->sphere_radius = epsilon;
}
/* Builds a bvh tree where nodes are the tesselated faces of the given dm */
@@ -950,10 +898,21 @@ BVHTree *bvhtree_from_mesh_faces(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, true, epsilon, vert, vert_allocated, face, face_allocated);
-
- return data->tree;
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(
+ data, tree, true, epsilon, vert, vert_allocated, face, face_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(vert);
+ }
+ if (face_allocated) {
+ MEM_freeN(face);
+ }
+ memset(data, 0, sizeof(*data));
+ }
+ return tree;
}
/**
@@ -964,8 +923,8 @@ BVHTree *bvhtree_from_mesh_faces(
* \param numFaces_active if >= 0, number of active faces to add to BVH tree (else will be computed from mask).
*/
BVHTree *bvhtree_from_mesh_faces_ex(
- BVHTreeFromMesh *data, MVert *vert, const bool vert_allocated,
- MFace *face, const int numFaces, const bool face_allocated,
+ BVHTreeFromMesh *data, const MVert *vert, const bool vert_allocated,
+ const MFace *face, const int numFaces, const bool face_allocated,
const BLI_bitmap *faces_mask, int faces_num_active,
float epsilon, int tree_type, int axis)
{
@@ -975,9 +934,10 @@ BVHTree *bvhtree_from_mesh_faces_ex(
faces_mask, faces_num_active);
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_faces_setup_data(data, tree, false, epsilon, vert, vert_allocated, face, face_allocated);
+ bvhtree_from_mesh_faces_setup_data(
+ data, tree, false, epsilon, vert, vert_allocated, face, face_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -1088,34 +1048,20 @@ static void bvhtree_from_mesh_looptri_setup_data(
{
memset(data, 0, sizeof(*data));
- if (tree) {
- data->tree = tree;
- data->cached = is_cached;
+ data->tree = tree;
+ data->cached = is_cached;
- data->nearest_callback = mesh_looptri_nearest_point;
- data->raycast_callback = mesh_looptri_spherecast;
- data->nearest_to_ray_callback = NULL;
+ data->nearest_callback = mesh_looptri_nearest_point;
+ data->raycast_callback = mesh_looptri_spherecast;
- data->vert = vert;
- data->vert_allocated = vert_allocated;
- data->loop = mloop;
- data->loop_allocated = loop_allocated;
- data->looptri = looptri;
- data->looptri_allocated = looptri_allocated;
+ data->vert = vert;
+ data->vert_allocated = vert_allocated;
+ data->loop = mloop;
+ data->loop_allocated = loop_allocated;
+ data->looptri = looptri;
+ data->looptri_allocated = looptri_allocated;
- data->sphere_radius = epsilon;
- }
- else {
- if (vert_allocated) {
- MEM_freeN((void *)vert);
- }
- if (loop_allocated) {
- MEM_freeN((void *)mloop);
- }
- if (looptri_allocated) {
- MEM_freeN((void *)looptri);
- }
- }
+ data->sphere_radius = epsilon;
}
/**
@@ -1160,7 +1106,6 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(
data->tree = tree;
data->nearest_callback = editmesh_looptri_nearest_point;
data->raycast_callback = editmesh_looptri_spherecast;
- data->nearest_to_ray_callback = NULL;
data->sphere_radius = 0.0f;
data->em = em;
data->cached = bvhCache != NULL;
@@ -1242,14 +1187,28 @@ BVHTree *bvhtree_from_mesh_looptri(
/* printf("BVHTree is already build, using cached tree\n"); */
}
- /* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_looptri_setup_data(
- data, tree, true, epsilon,
- mvert, vert_allocated,
- mloop, loop_allocated,
- looptri, looptri_allocated);
+ if (tree) {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_looptri_setup_data(
+ data, tree, true, epsilon,
+ mvert, vert_allocated,
+ mloop, loop_allocated,
+ looptri, looptri_allocated);
+ }
+ else {
+ if (vert_allocated) {
+ MEM_freeN(mvert);
+ }
+ if (loop_allocated) {
+ MEM_freeN(mloop);
+ }
+ if (looptri_allocated) {
+ MEM_freeN((void *)looptri);
+ }
+ memset(data, 0, sizeof(*data));
+ }
- return data->tree;
+ return tree;
}
BVHTree *bvhtree_from_mesh_looptri_ex(
@@ -1272,7 +1231,7 @@ BVHTree *bvhtree_from_mesh_looptri_ex(
mloop, loop_allocated,
looptri, looptri_allocated);
- return data->tree;
+ return tree;
}
/** \} */
@@ -1292,29 +1251,27 @@ void free_bvhtree_from_editmesh(struct BVHTreeFromEditMesh *data)
/* Frees data allocated by a call to bvhtree_from_mesh_*. */
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
{
- if (data->tree) {
- if (!data->cached) {
- BLI_bvhtree_free(data->tree);
- }
-
- if (data->vert_allocated) {
- MEM_freeN((void *)data->vert);
- }
- if (data->edge_allocated) {
- MEM_freeN((void *)data->edge);
- }
- if (data->face_allocated) {
- MEM_freeN((void *)data->face);
- }
- if (data->loop_allocated) {
- MEM_freeN((void *)data->loop);
- }
- if (data->looptri_allocated) {
- MEM_freeN((void *)data->looptri);
- }
+ if (data->tree && !data->cached) {
+ BLI_bvhtree_free(data->tree);
+ }
- memset(data, 0, sizeof(*data));
+ if (data->vert_allocated) {
+ MEM_freeN((void *)data->vert);
+ }
+ if (data->edge_allocated) {
+ MEM_freeN((void *)data->edge);
+ }
+ if (data->face_allocated) {
+ MEM_freeN((void *)data->face);
}
+ if (data->loop_allocated) {
+ MEM_freeN((void *)data->loop);
+ }
+ if (data->looptri_allocated) {
+ MEM_freeN((void *)data->looptri);
+ }
+
+ memset(data, 0, sizeof(*data));
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 978204f1cf5..be75048492c 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -633,7 +633,7 @@ static bool camera_frame_fit_calc_from_data(
/* don't move the camera, just yield the fit location */
/* r_scale only valid/useful for ortho cameras */
bool BKE_camera_view_frame_fit_to_scene(
- Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+ Scene *scene, SceneLayer *sl, Object *camera_ob, float r_co[3], float *r_scale)
{
CameraParams params;
CameraViewFrameData data_cb;
@@ -644,7 +644,7 @@ bool BKE_camera_view_frame_fit_to_scene(
camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
/* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+ BKE_scene_foreach_display_point(scene, sl, camera_to_frame_view_cb, &data_cb);
return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 483fa977aff..3f5b6ca580f 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -372,36 +372,6 @@ static void cdDM_drawVerts(DerivedMesh *dm)
GPU_buffers_unbind();
}
-static void cdDM_drawUVEdges(DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- const MPoly *mpoly = cddm->mpoly;
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
-
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
@@ -2008,7 +1978,6 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawVerts = cdDM_drawVerts;
- dm->drawUVEdges = cdDM_drawUVEdges;
dm->drawEdges = cdDM_drawEdges;
dm->drawLooseEdges = cdDM_drawLooseEdges;
dm->drawMappedEdges = cdDM_drawMappedEdges;
@@ -2428,8 +2397,12 @@ static DerivedMesh *cddm_copy_ex(DerivedMesh *source,
dm->cd_flag = source->cd_flag;
dm->dirty = source->dirty;
- /* Tessellation data is never copied, so tag it here. */
- dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+ /* Tessellation data is never copied, so tag it here.
+ * Only tag dirty layers if we really ignored tessellation faces.
+ */
+ if (!copy_tessface_data) {
+ dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
+ }
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 162525c7cd5..8190a7c2a8b 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -868,12 +868,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
return 0;
}
- for ( i = 0; i < dm->getNumVerts(dm); i++) {
- if ((!(cloth->verts[i].flags & CLOTH_VERT_FLAG_PINNED)) && (cloth->verts[i].goal > ALMOST_ZERO)) {
- cloth_add_spring (clmd, i, i, 0.0, CLOTH_SPRING_TYPE_GOAL);
- }
- }
-
// init our solver
BPH_cloth_solver_init(ob, clmd);
@@ -943,37 +937,6 @@ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
}
}
-// be careful: implicit solver has to be resettet when using this one!
-// --> only for implicit handling of this spring!
-int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type)
-{
- Cloth *cloth = clmd->clothObject;
- ClothSpring *spring = NULL;
-
- if (cloth) {
- // TODO: look if this spring is already there
-
- spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" );
-
- if (!spring)
- return 0;
-
- spring->ij = indexA;
- spring->kl = indexB;
- spring->restlen = restlength;
- spring->type = spring_type;
- spring->flags = 0;
- spring->stiffness = 0;
-
- cloth->numsprings++;
-
- BLI_linklist_prepend ( &cloth->springs, spring );
-
- return 1;
- }
- return 0;
-}
-
static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num)
{
if (edgelist) {
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 289586153ea..b16162dfbc0 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -24,6 +24,8 @@
* \ingroup bke
*/
+#include <string.h>
+
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
#include "BLI_iterator.h"
@@ -44,6 +46,7 @@
#include "MEM_guardedalloc.h"
+
/**
* Add a collection to a collection ListBase and syncronize all render layers
* The ListBase is NULL when the collection is to be added to the master collection
@@ -61,9 +64,7 @@ SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, co
sc_parent = sc_master;
}
- BLI_strncpy(sc->name, name, sizeof(sc->name));
- BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
-
+ BKE_collection_rename(scene, sc, name);
BLI_addtail(&sc_parent->scene_collections, sc);
BKE_layer_sync_new_scene_collection(scene, sc_parent, sc);
@@ -93,12 +94,11 @@ static void collection_free(SceneCollection *sc)
/**
* Unlink the collection recursively
- * return true if unlinked
+ * \return true if unlinked.
*/
static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
{
- for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next)
- {
+ for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) {
if (sc == sc_gone) {
BLI_remlink(&sc_parent->scene_collections, sc_gone);
return true;
@@ -117,9 +117,8 @@ static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_g
static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc)
{
LayerCollection *lc = lb->first;
- while(lc) {
+ while (lc) {
if (lc->scene_collection == sc) {
- BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
BKE_layer_collection_free(sl, lc);
BLI_remlink(lb, lc);
@@ -165,7 +164,6 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
/* check all layers that use this collection and clear them */
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
layer_collection_remove(sl, &sl->layer_collections, sc);
- BKE_scene_layer_base_flag_recalculate(sl);
sl->active_collection = 0;
}
@@ -176,20 +174,55 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
/**
* Returns the master collection
*/
-SceneCollection *BKE_collection_master(Scene *scene)
+SceneCollection *BKE_collection_master(const Scene *scene)
{
return scene->collection;
}
+struct UniqueNameCheckData {
+ ListBase *lb;
+ SceneCollection *lookup_sc;
+};
+
+static bool collection_unique_name_check(void *arg, const char *name)
+{
+ struct UniqueNameCheckData *data = arg;
+
+ for (SceneCollection *sc = data->lb->first; sc; sc = sc->next) {
+ struct UniqueNameCheckData child_data = {.lb = &sc->scene_collections, .lookup_sc = data->lookup_sc};
+
+ if (sc != data->lookup_sc) {
+ if (STREQ(sc->name, name)) {
+ return true;
+ }
+ }
+ if (collection_unique_name_check(&child_data, name)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name)
+{
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ struct UniqueNameCheckData data = {.lb = &sc_master->scene_collections, .lookup_sc = sc};
+
+ BLI_strncpy(sc->name, name, sizeof(sc->name));
+ BLI_uniquename_cb(collection_unique_name_check, &data, DATA_("Collection"), '.', sc->name, sizeof(sc->name));
+}
+
/**
* Free (or release) any data used by the master collection (does not free the master collection itself).
* Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree
*/
-void BKE_collection_master_free(Scene *scene){
+void BKE_collection_master_free(Scene *scene)
+{
collection_free(BKE_collection_master(scene));
}
-static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+static void collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob)
{
BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
id_us_plus((ID *)ob);
@@ -199,7 +232,7 @@ static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
/**
* Add object to collection
*/
-void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+void BKE_collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob)
{
if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
/* don't add the same object twice */
@@ -214,7 +247,6 @@ void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
*/
void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
{
- SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
@@ -225,9 +257,10 @@ void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst
}
/**
- * Remove object from collection
+ * Remove object from collection.
+ * \param bmain: Can be NULL if free_us is false.
*/
-void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
+void BKE_collection_object_remove(Main *bmain, const Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
{
LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
@@ -251,13 +284,21 @@ void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc
}
/**
+ * Move object from a collection into another
+ */
+void BKE_collection_object_move(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+{
+ BKE_collection_object_add(scene, sc_dst, ob);
+ BKE_collection_object_remove(NULL, scene, sc_src, ob, false);
+}
+
+/**
* Remove object from all collections of scene
*/
void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
{
BKE_scene_remove_rigidbody_object(scene, ob);
- SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
BKE_collection_object_remove(bmain, scene, sc, ob, free_us);
@@ -266,6 +307,152 @@ void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const
}
/* ---------------------------------------------------------------------- */
+/* Outliner drag and drop */
+
+/**
+ * Find and return the SceneCollection that has \a sc_child as one of its directly
+ * nested SceneCollection.
+ *
+ * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection
+ */
+static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent)
+{
+ for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
+ if (sc_nested == sc_child) {
+ return sc_parent;
+ }
+
+ SceneCollection *found = find_collection_parent(sc_child, sc_nested);
+ if (found) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Check if \a sc_reference is nested to \a sc_parent SceneCollection
+ */
+static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent)
+{
+ return find_collection_parent(sc_reference, sc_parent) != NULL;
+}
+
+bool BKE_collection_move_above(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ /* Master Layer can't be moved around*/
+ if (ELEM(sc_master, sc_src, sc_dst)) {
+ return false;
+ }
+
+ /* collection is already where we wanted it to be */
+ if (sc_dst->prev == sc_src) {
+ return false;
+ }
+
+ /* We can't move a collection fs the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
+ BLI_assert(sc_src_parent);
+ BLI_assert(sc_dst_parent);
+
+ /* Remove sc_src from its parent */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Re-insert it where it belongs */
+ BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(scene, sc_src_parent);
+ BKE_layer_collection_resync(scene, sc_dst_parent);
+
+ return true;
+}
+
+bool BKE_collection_move_below(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ /* Master Layer can't be moved around*/
+ if (ELEM(sc_master, sc_src, sc_dst)) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (sc_dst->next == sc_src) {
+ return false;
+ }
+
+ /* We can't move a collection if the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
+ BLI_assert(sc_src_parent);
+ BLI_assert(sc_dst_parent);
+
+ /* Remove sc_src from its parent */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Re-insert it where it belongs */
+ BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(scene, sc_src_parent);
+ BKE_layer_collection_resync(scene, sc_dst_parent);
+
+ return true;
+}
+
+bool BKE_collection_move_into(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ if (sc_src == sc_master) {
+ return false;
+ }
+
+ /* We can't move a collection if the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ BLI_assert(sc_src_parent);
+
+ /* collection is already where we wanted it to be */
+ if (sc_dst->scene_collections.last == sc_src) {
+ return false;
+ }
+
+ /* Remove sc_src from it */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Insert sc_src into sc_dst */
+ BLI_addtail(&sc_dst->scene_collections, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(scene, sc_src_parent);
+ BKE_layer_collection_resync(scene, sc_dst);
+
+ return true;
+}
+
+/* ---------------------------------------------------------------------- */
/* Iteractors */
/* scene collection iteractor */
@@ -273,7 +460,7 @@ typedef struct SceneCollectionsIteratorData {
Scene *scene;
void **array;
int tot, cur;
- } SceneCollectionsIteratorData;
+} SceneCollectionsIteratorData;
static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
{
@@ -384,7 +571,7 @@ void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in)
BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene);
SceneCollection *sc = data->scene_collection_iter.current;
- iter->current = sc->objects.first;
+ iter->current = sc->objects.first ? ((LinkData *)sc->objects.first)->data : NULL;
iter->valid = true;
if (iter->current == NULL) {
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index b5f76240c0b..23cfee721ae 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -512,9 +512,9 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
// return all collision objects in scene
// collision object will exclude self
-Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int UNUSED(layer), unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
- BaseLegacy *base;
+ Base *base;
Object **objs;
GroupObject *go;
unsigned int numobj= 0, maxobj= 100;
@@ -532,9 +532,9 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int
Scene *sce_iter;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if ( base->lay & layer )
+ if ((base->flag & BASE_VISIBLED) != 0) {
add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type);
-
+ }
}
}
@@ -596,11 +596,11 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
}
else {
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if (!self || (base->lay & self->lay))
+ if (!self || ((base->flag & BASE_VISIBLED) != 0))
add_collider_cache_object(&objs, base->object, self, 0);
}
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 4f3ffed41bc..b3a0895d063 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -508,7 +508,7 @@ static void calchandle_curvemap(
if ((bezt->h2 == HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
const float ydiff1 = prev->vec[1][1] - bezt->vec[1][1];
const float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
- if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f)||
+ if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) ||
(ydiff1 >= 0.0f && ydiff2 >= 0.0f))
{
bezt->vec[2][1] = bezt->vec[1][1];
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index a7c53dda8c7..20a3d4ac7e0 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -39,6 +39,8 @@
#include "DNA_linestyle_types.h"
#include "DNA_gpencil_types.h"
+#include "DEG_depsgraph.h"
+
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_threads.h"
@@ -815,14 +817,6 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C)
return NULL;
}
-struct SpaceCollections *CTX_wm_space_collections(const bContext *C)
-{
- ScrArea *sa = CTX_wm_area(C);
- if (sa && sa->spacetype == SPACE_COLLECTIONS)
- return sa->spacedata.first;
- return NULL;
-}
-
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
{
C->wm.manager = wm;
@@ -914,7 +908,7 @@ SceneLayer *CTX_data_scene_layer(const bContext *C)
return sl;
}
else {
- return BKE_scene_layer_active(CTX_data_scene(C));
+ return BKE_scene_layer_context_active(CTX_data_scene(C));
}
}
@@ -1217,3 +1211,8 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
+Depsgraph *CTX_data_depsgraph(const bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ return scene->depsgraph;
+}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 90a514781d7..439abb1d593 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -89,20 +89,33 @@ void BKE_curve_editfont_free(Curve *cu)
}
}
-void BKE_curve_editNurb_keyIndex_free(EditNurb *editnurb)
+static void curve_editNurb_keyIndex_cv_free_cb(void *val)
{
- if (!editnurb->keyindex) {
+ CVKeyIndex *index = val;
+ MEM_freeN(index->orig_cv);
+ MEM_freeN(val);
+}
+
+void BKE_curve_editNurb_keyIndex_delCV(GHash *keyindex, const void *cv)
+{
+ BLI_assert(keyindex != NULL);
+ BLI_ghash_remove(keyindex, cv, NULL, curve_editNurb_keyIndex_cv_free_cb);
+}
+
+void BKE_curve_editNurb_keyIndex_free(GHash **keyindex)
+{
+ if (!(*keyindex)) {
return;
}
- BLI_ghash_free(editnurb->keyindex, NULL, MEM_freeN);
- editnurb->keyindex = NULL;
+ BLI_ghash_free(*keyindex, NULL, curve_editNurb_keyIndex_cv_free_cb);
+ *keyindex = NULL;
}
void BKE_curve_editNurb_free(Curve *cu)
{
if (cu->editnurb) {
BKE_nurbList_free(&cu->editnurb->nurbs);
- BKE_curve_editNurb_keyIndex_free(cu->editnurb);
+ BKE_curve_editNurb_keyIndex_free(&cu->editnurb->keyindex);
MEM_freeN(cu->editnurb);
cu->editnurb = NULL;
}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index c9f0b8ec9ca..7c3f0ac630d 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -33,14 +33,10 @@
/** \file blender/blenkernel/intern/customdata.c
* \ingroup bke
*/
-
-
-#include <math.h>
-#include <string.h>
-#include <assert.h>
#include "MEM_guardedalloc.h"
+#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_ID.h"
@@ -62,20 +58,16 @@
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
-#include "data_transfer_intern.h"
-
#include "bmesh.h"
-#include <math.h>
-#include <string.h>
+/* only for customdata_data_transfer_interp_normal_normals */
+#include "data_transfer_intern.h"
/* number of layers to add when growing a CustomData object */
#define CUSTOMDATA_GROW 5
/* ensure typemap size is ok */
-BLI_STATIC_ASSERT(sizeof(((CustomData *)NULL)->typemap) /
- sizeof(((CustomData *)NULL)->typemap[0]) == CD_NUMTYPES,
- "size mismatch");
+BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)NULL)->typemap) == CD_NUMTYPES, "size mismatch");
/********************* Layer type information **********************/
@@ -805,18 +797,15 @@ static void layerInterp_mloopcol(
const float *sub_weights, int count, void *dest)
{
MLoopCol *mc = dest;
- int i;
- const float *sub_weight;
struct {
float a;
float r;
float g;
float b;
- } col;
- col.a = col.r = col.g = col.b = 0;
+ } col = {0};
- sub_weight = sub_weights;
- for (i = 0; i < count; ++i) {
+ const float *sub_weight = sub_weights;
+ for (int i = 0; i < count; ++i) {
float weight = weights ? weights[i] : 1;
const MLoopCol *src = sources[i];
if (sub_weights) {
@@ -833,19 +822,16 @@ static void layerInterp_mloopcol(
col.a += src->a * weight;
}
}
-
+
+
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
- CLAMP(col.a, 0.0f, 255.0f);
- CLAMP(col.r, 0.0f, 255.0f);
- CLAMP(col.g, 0.0f, 255.0f);
- CLAMP(col.b, 0.0f, 255.0f);
- /* delay writing to the destination incase dest is in sources */
- mc->r = (int)col.r;
- mc->g = (int)col.g;
- mc->b = (int)col.b;
- mc->a = (int)col.a;
+ /* also delay writing to the destination incase dest is in sources */
+ mc->r = CLAMPIS(iroundf(col.r), 0, 255);
+ mc->g = CLAMPIS(iroundf(col.g), 0, 255);
+ mc->b = CLAMPIS(iroundf(col.b), 0, 255);
+ mc->a = CLAMPIS(iroundf(col.a), 0, 255);
}
static int layerMaxNum_mloopcol(void)
@@ -1068,15 +1054,10 @@ static void layerInterp_mcol(
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
- CLAMP(col[j].a, 0.0f, 255.0f);
- CLAMP(col[j].r, 0.0f, 255.0f);
- CLAMP(col[j].g, 0.0f, 255.0f);
- CLAMP(col[j].b, 0.0f, 255.0f);
-
- mc[j].a = (int)col[j].a;
- mc[j].r = (int)col[j].r;
- mc[j].g = (int)col[j].g;
- mc[j].b = (int)col[j].b;
+ mc[j].a = CLAMPIS(iroundf(col[j].a), 0, 255);
+ mc[j].r = CLAMPIS(iroundf(col[j].r), 0, 255);
+ mc[j].g = CLAMPIS(iroundf(col[j].g), 0, 255);
+ mc[j].b = CLAMPIS(iroundf(col[j].b), 0, 255);
}
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index c5b8a18fd65..f0b1363e647 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -228,6 +228,18 @@ bool DAG_is_acyclic(Scene *UNUSED(scene))
return false;
}
+/* ************************ DAG ********************* */
+
+/**
+ * Get the object as properly evaluated by depsgraph.
+ */
+Object *DAG_get_object(Depsgraph *depsgraph, Object *ob)
+{
+ /* XXX TODO */
+ UNUSED_VARS(depsgraph);
+ return ob;
+}
+
/* ************************************
* This functions are to be supported *
* ************************************
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 49db75a0474..f8a9d57f579 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -819,7 +819,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
if (editmode)
required_mode |= eModifierMode_Editmode;
- if (cu->editnurb == NULL) {
+ if (!editmode) {
keyVerts = BKE_key_evaluate_object(ob, &numVerts);
if (keyVerts) {
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 39d06a13e6e..fe55909bcd5 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2460,8 +2460,7 @@ static void dynamic_paint_find_island_border(
const unsigned int *other_loop_idx = mlooptri[lt_index].tri;
/* Check edges for match, looping in the same order as the outer loop. */
- for (int j = 0; j < 3; j++)
- {
+ for (int j = 0; j < 3; j++) {
const int overt0 = mloop[other_loop_idx[(j + 0)]].v;
const int overt1 = mloop[other_loop_idx[(j + 1) % 3]].v;
@@ -2525,8 +2524,7 @@ static void dynamic_paint_find_island_border(
int final_pixel[2] = { (int)floorf(tgt_pixel[0] * w), (int)floorf(tgt_pixel[1] * h) };
/* If current pixel uv is outside of texture */
- if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h)
- {
+ if (final_pixel[0] < 0 || final_pixel[0] >= w || final_pixel[1] < 0 || final_pixel[1] >= h) {
if (bdata->best_index == NOT_FOUND)
bdata->best_index = OUT_OF_TEXTURE;
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index e7c0e69b1cb..19a27499ff0 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -642,10 +642,10 @@ static void emDM_recalcLoopTri(DerivedMesh *dm)
MLoopTri *lt = &mlooptri[i];
ARRAY_SET_ITEMS(
- lt->tri,
- BM_elem_index_get(ltri[0]),
- BM_elem_index_get(ltri[1]),
- BM_elem_index_get(ltri[2]));
+ lt->tri,
+ BM_elem_index_get(ltri[0]),
+ BM_elem_index_get(ltri[1]),
+ BM_elem_index_get(ltri[2]));
lt->poly = BM_elem_index_get(ltri[0]->f);
}
}
@@ -810,39 +810,6 @@ static void emDM_drawMappedEdgesInterp(
}
}
-static void emDM_drawUVEdges(DerivedMesh *dm)
-{
- EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
- BMesh *bm = bmdm->em->bm;
- BMFace *efa;
- BMIter iter;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (UNLIKELY(cd_loop_uv_offset == -1)) {
- return;
- }
-
- glBegin(GL_LINES);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- const float *uv, *uv_prev;
-
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
- do {
- uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
- glVertex2fv(uv);
- glVertex2fv(uv_prev);
- uv_prev = uv;
- } while ((l_iter = l_iter->next) != l_first);
- }
- glEnd();
-}
-
static void emDM_foreachMappedLoop(
DerivedMesh *dm,
void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
@@ -2280,7 +2247,6 @@ DerivedMesh *getEditDerivedBMesh(
bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
bmdm->dm.drawFacesTex = emDM_drawFacesTex;
bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
- bmdm->dm.drawUVEdges = emDM_drawUVEdges;
bmdm->dm.release = emDM_release;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 668d4d6c9e2..c58e304db6c 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -848,6 +848,14 @@ static void do_physical_effector(EffectorCache *eff, EffectorData *efd, Effected
break;
case PFIELD_FORCE:
normalize_v3(force);
+ if (pd->flag & PFIELD_GRAVITATION){ /* Option: Multiply by 1/distance^2 */
+ if (efd->distance < FLT_EPSILON){
+ strength = 0.0f;
+ }
+ else {
+ strength *= powf(efd->distance, -2.0f);
+ }
+ }
mul_v3_fl(force, strength * efd->falloff);
break;
case PFIELD_VORTEX:
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index c67a61a5aad..7dbc43e0a32 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1217,6 +1217,7 @@ bool driver_get_variable_property(
return true;
}
+#if 0
/* Helper function to obtain a pointer to a Pose Channel (for evaluating drivers) */
static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dtar)
{
@@ -1239,6 +1240,32 @@ static bPoseChannel *dtar_get_pchan_ptr(ChannelDriver *driver, DriverTarget *dta
return NULL;
}
}
+#endif
+
+static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
+{
+ short valid_targets = 0;
+
+ DRIVER_TARGETS_USED_LOOPER(dvar)
+ {
+ Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+
+ /* check if this target has valid data */
+ if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
+ /* invalid target, so will not have enough targets */
+ driver->flag |= DRIVER_FLAG_INVALID;
+ dtar->flag |= DTAR_FLAG_INVALID;
+ }
+ else {
+ /* target seems to be OK now... */
+ dtar->flag &= ~DTAR_FLAG_INVALID;
+ valid_targets++;
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END
+
+ return valid_targets;
+}
/* ......... */
@@ -1252,62 +1279,54 @@ static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar)
/* evaluate 'rotation difference' driver variable */
static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
{
- DriverTarget *dtar1 = &dvar->targets[0];
- DriverTarget *dtar2 = &dvar->targets[1];
- bPoseChannel *pchan, *pchan2;
- float q1[4], q2[4], quat[4], angle;
-
- /* get pose channels, and check if we've got two */
- pchan = dtar_get_pchan_ptr(driver, dtar1);
- pchan2 = dtar_get_pchan_ptr(driver, dtar2);
-
- if (ELEM(NULL, pchan, pchan2)) {
- /* disable this driver, since it doesn't work correctly... */
- driver->flag |= DRIVER_FLAG_INVALID;
-
- /* check what the error was */
- if ((pchan == NULL) && (pchan2 == NULL)) {
- if (G.debug & G_DEBUG) {
- printf("Driver Evaluation Error: Rotational difference failed - first 2 targets invalid\n");
- }
-
- dtar1->flag |= DTAR_FLAG_INVALID;
- dtar2->flag |= DTAR_FLAG_INVALID;
- }
- else if (pchan == NULL) {
- if (G.debug & G_DEBUG) {
- printf("Driver Evaluation Error: Rotational difference failed - first target not valid PoseChannel\n");
- }
-
- dtar1->flag |= DTAR_FLAG_INVALID;
- dtar2->flag &= ~DTAR_FLAG_INVALID;
- }
- else if (pchan2 == NULL) {
- if (G.debug & G_DEBUG) {
- printf("Driver Evaluation Error: Rotational difference failed - second target not valid PoseChannel\n");
- }
-
- dtar1->flag &= ~DTAR_FLAG_INVALID;
- dtar2->flag |= DTAR_FLAG_INVALID;
+ short valid_targets = driver_check_valid_targets(driver, dvar);
+
+ /* make sure we have enough valid targets to use - all or nothing for now... */
+ if (driver_check_valid_targets(driver, dvar) != 2) {
+ if (G.debug & G_DEBUG) {
+ printf("RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)\n",
+ valid_targets, dvar->targets[0].id, dvar->targets[1].id);
}
-
- /* stop here... */
return 0.0f;
}
- else {
- dtar1->flag &= ~DTAR_FLAG_INVALID;
- dtar2->flag &= ~DTAR_FLAG_INVALID;
+
+ float (*mat[2])[4];
+
+ /* NOTE: for now, these are all just worldspace */
+ for (int i = 0; i < 2; i++) {
+ /* get pointer to loc values to store in */
+ DriverTarget *dtar = &dvar->targets[i];
+ Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ bPoseChannel *pchan;
+
+ /* after the checks above, the targets should be valid here... */
+ BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB));
+
+ /* try to get posechannel */
+ pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name);
+
+ /* check if object or bone */
+ if (pchan) {
+ /* bone */
+ mat[i] = pchan->pose_mat;
+ }
+ else {
+ /* object */
+ mat[i] = ob->obmat;
+ }
}
-
+
+ float q1[4], q2[4], quat[4], angle;
+
/* use the final posed locations */
- mat4_to_quat(q1, pchan->pose_mat);
- mat4_to_quat(q2, pchan2->pose_mat);
-
+ mat4_to_quat(q1, mat[0]);
+ mat4_to_quat(q2, mat[1]);
+
invert_qt_normalized(q1);
mul_qt_qtqt(quat, q1, q2);
angle = 2.0f * (saacos(quat[0]));
angle = ABS(angle);
-
+
return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle);
}
@@ -1317,32 +1336,8 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
{
float loc1[3] = {0.0f, 0.0f, 0.0f};
float loc2[3] = {0.0f, 0.0f, 0.0f};
- short valid_targets = 0;
-
- /* Perform two passes
- *
- * FIRST PASS - to just check that everything works...
- * NOTE: we use loops here to reduce code duplication, though in practice,
- * there can only be 2 items or else we run into some problems later
- */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
-
- /* check if this target has valid data */
- if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
- /* invalid target, so will not have enough targets */
- driver->flag |= DRIVER_FLAG_INVALID;
- dtar->flag |= DTAR_FLAG_INVALID;
- }
- else {
- /* target seems to be OK now... */
- dtar->flag &= ~DTAR_FLAG_INVALID;
- valid_targets++;
- }
- }
- DRIVER_TARGETS_LOOPER_END
-
+ short valid_targets = driver_check_valid_targets(driver, dvar);
+
/* make sure we have enough valid targets to use - all or nothing for now... */
if (valid_targets < dvar->num_targets) {
if (G.debug & G_DEBUG) {
@@ -1351,8 +1346,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
}
return 0.0f;
}
-
-
+
/* SECOND PASS: get two location values */
/* NOTE: for now, these are all just worldspace */
DRIVER_TARGETS_USED_LOOPER(dvar)
@@ -1570,7 +1564,7 @@ static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = {
BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF)
dvar_eval_rotDiff, /* eval callback */
2, /* number of targets used */
- {"Bone 1", "Bone 2"}, /* UI names for targets */
+ {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */
{DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */
END_DVAR_TYPEDEF,
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index b2641b110f8..65d3f9e93fc 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -130,18 +130,22 @@ void IDP_FreeIDPArray(IDProperty *prop)
MEM_freeN(prop->data.pointer);
}
-/*shallow copies item*/
+/* shallow copies item */
void IDP_SetIndexArray(IDProperty *prop, int index, IDProperty *item)
{
IDProperty *old;
BLI_assert(prop->type == IDP_IDPARRAY);
+ if (index >= prop->len || index < 0)
+ return;
+
old = GETPROP(prop, index);
- if (index >= prop->len || index < 0) return;
- if (item != old) IDP_FreeProperty(old);
-
- memcpy(GETPROP(prop, index), item, sizeof(IDProperty));
+ if (item != old) {
+ IDP_FreeProperty(old);
+
+ memcpy(old, item, sizeof(IDProperty));
+ }
}
IDProperty *IDP_GetIndexArray(IDProperty *prop, int index)
@@ -468,6 +472,7 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop)
BLI_assert(prop->type == IDP_GROUP);
newp = idp_generic_copy(prop);
newp->len = prop->len;
+ newp->subtype = prop->subtype;
for (link = prop->data.group.first; link; link = link->next) {
BLI_addtail(&newp->data.group, IDP_CopyProperty(link));
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index a2d94ccc478..318f6480aaf 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -3159,7 +3159,7 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
struct ImBuf *ibuf;
char name[FILE_MAX];
int flag;
- ImageUser iuser_t;
+ ImageUser iuser_t = {0};
/* XXX temp stuff? */
if (ima->lastframe != frame)
@@ -3167,8 +3167,12 @@ static ImBuf *load_sequence_single(Image *ima, ImageUser *iuser, int frame, cons
ima->lastframe = frame;
- if (iuser)
+ if (iuser) {
iuser_t = *iuser;
+ }
+ else {
+ /* TODO(sergey): Do we need to initialize something here? */
+ }
iuser_t.view = view_id;
BKE_image_user_file_path(&iuser_t, ima, name);
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index b0671f33094..54cfae620a1 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -67,7 +67,7 @@
#include "BKE_deform.h"
-/* Workaround for cyclic depenndnecy with curves.
+/* Workaround for cyclic dependency with curves.
* In such case curve_cache might not be ready yet,
*/
#define CYCLIC_DEPENDENCY_WORKAROUND
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index ef4816af54d..caa60450133 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -24,14 +24,18 @@
* \ingroup bke
*/
+#include <string.h>
+
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_string_utils.h"
#include "BLT_translation.h"
-#include "BKE_layer.h"
#include "BKE_collection.h"
+#include "BKE_depsgraph.h"
+#include "BKE_global.h"
+#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -42,25 +46,29 @@
#include "DNA_node_types.h"
#include "DNA_scene_types.h"
+#include "DRW_engine.h"
+
#include "MEM_guardedalloc.h"
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+
/* prototype */
struct CollectionEngineSettingsCB_Type;
static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
-static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
+static LayerCollection *layer_collection_add(SceneLayer *sl, LayerCollection *parent, SceneCollection *sc);
static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
-static CollectionEngineSettings *collection_engine_settings_create(struct CollectionEngineSettingsCB_Type *ces_type);
-static void layer_collection_engine_settings_free(LayerCollection *lc);
-static void layer_collection_create_engine_settings(LayerCollection *lc);
-static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name);
+static IDProperty *collection_engine_settings_create(struct CollectionEngineSettingsCB_Type *ces_type, const bool populate);
+static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name);
+static void collection_engine_settings_init(IDProperty *root, const bool populate);
static void object_bases_Iterator_next(Iterator *iter, const int flag);
/* RenderLayer */
/**
* Returns the SceneLayer to be used for rendering
+ * Most of the time BKE_scene_layer_context_active should be used instead
*/
-SceneLayer *BKE_scene_layer_active(struct Scene *scene)
+SceneLayer *BKE_scene_layer_render_active(const Scene *scene)
{
SceneLayer *sl = BLI_findlink(&scene->render_layers, scene->active_layer);
BLI_assert(sl);
@@ -68,6 +76,17 @@ SceneLayer *BKE_scene_layer_active(struct Scene *scene)
}
/**
+ * Returns the SceneLayer to be used for drawing, outliner, and
+ * other context related areas.
+ */
+SceneLayer *BKE_scene_layer_context_active(Scene *scene)
+{
+ /* waiting for workspace to get the layer from context*/
+ TODO_LAYER_CONTEXT;
+ return BKE_scene_layer_render_active(scene);
+}
+
+/**
* Add a new renderlayer
* by default, a renderlayer has the master collection
*/
@@ -87,7 +106,7 @@ SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
SceneCollection *sc = BKE_collection_master(scene);
- layer_collection_add(sl, &sl->layer_collections, sc);
+ layer_collection_add(sl, NULL, sc);
return sl;
}
@@ -129,6 +148,13 @@ bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
void BKE_scene_layer_free(SceneLayer *sl)
{
sl->basact = NULL;
+
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (base->collection_properties) {
+ IDP_FreeProperty(base->collection_properties);
+ MEM_freeN(base->collection_properties);
+ }
+ }
BLI_freelistN(&sl->object_bases);
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
@@ -176,7 +202,7 @@ static bool find_scene_collection_in_scene_collections(ListBase *lb, const Layer
/**
* Find the SceneLayer a LayerCollection belongs to
*/
-SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
+SceneLayer *BKE_scene_layer_find_from_collection(const Scene *scene, LayerCollection *lc)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
@@ -210,7 +236,7 @@ void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase)
}
}
-static void scene_layer_object_base_unref(SceneLayer* sl, Base *base)
+static void scene_layer_object_base_unref(SceneLayer *sl, Base *base)
{
base->refcount--;
@@ -220,125 +246,14 @@ static void scene_layer_object_base_unref(SceneLayer* sl, Base *base)
sl->basact = NULL;
}
- BLI_remlink(&sl->object_bases, base);
- MEM_freeN(base);
- }
-}
-
-static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
-{
- bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
- /* an object can only be selected if it's visible */
- bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
-
- for (LinkData *link = lc->object_bases.first; link; link = link->next) {
- Base *base = link->data;
-
- if (is_visible) {
- base->flag |= BASE_VISIBLED;
- }
- else {
- base->flag &= ~BASE_VISIBLED;
+ if (base->collection_properties) {
+ IDP_FreeProperty(base->collection_properties);
+ MEM_freeN(base->collection_properties);
}
- if (is_selectable) {
- base->flag |= BASE_SELECTABLED;
- }
- else {
- base->flag &= ~BASE_SELECTABLED;
- }
- }
-
- for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
- layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
- }
-}
-
-/**
- * Re-evaluate the ObjectBase flags for SceneLayer
- */
-void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
-{
- for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
- layer_collection_base_flag_recalculate(lc, true, true);
- }
-
- /* if base is not selectabled, clear select */
- for (Base *base = sl->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_SELECTABLED) == 0) {
- base->flag &= ~BASE_SELECTED;
- }
- }
-}
-
-/**
- * Tag Scene Layer to recalculation
- *
- * Temporary function, waiting for real depsgraph
- */
-void BKE_scene_layer_engine_settings_recalculate(SceneLayer *sl)
-{
- sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
- for (Base *base = sl->object_bases.first; base; base = base->next) {
- base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
- }
-}
-
-/**
- * Tag Object in SceneLayer to recalculation
- *
- * Temporary function, waiting for real depsgraph
- */
-void BKE_scene_layer_engine_settings_object_recalculate(SceneLayer *sl, Object *ob)
-{
- Base *base = BLI_findptr(&sl->object_bases, ob, offsetof(Base, object));
- if (base) {
- sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
- base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
- }
-}
-
-/**
- * Tag all Objects in LayerCollection to recalculation
- *
- * Temporary function, waiting for real depsgraph
- */
-void BKE_scene_layer_engine_settings_collection_recalculate(SceneLayer *sl, LayerCollection *lc)
-{
- sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
-
- for (LinkData *link = lc->object_bases.first; link; link = link->next) {
- Base *base = (Base *)link->data;
- base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
- }
-
- for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
- BKE_scene_layer_engine_settings_collection_recalculate(sl, lcn);
- }
-}
-
-/**
- * Re-calculate the engine settings for all the objects in SceneLayer
- *
- * Temporary function, waiting for real depsgraph
- */
-void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl, const char *engine_name)
-{
- if ((sl->flag & SCENE_LAYER_ENGINE_DIRTY) == 0) {
- return;
- }
-
- /* do the complete settings update */
- for (Base *base = sl->object_bases.first; base; base = base->next) {
- if (((base->flag & BASE_DIRTY_ENGINE_SETTINGS) != 0) && \
- (base->flag & BASE_VISIBLED) != 0)
- {
- scene_layer_engine_settings_update(sl, base->object, engine_name);
- base->flag &= ~BASE_DIRTY_ENGINE_SETTINGS;
- }
+ BLI_remlink(&sl->object_bases, base);
+ MEM_freeN(base);
}
-
- sl->flag &= ~SCENE_LAYER_ENGINE_DIRTY;
}
/**
@@ -356,7 +271,11 @@ static Base *object_base_add(SceneLayer *sl, Object *ob)
/* do not bump user count, leave it for SceneCollections */
base->object = ob;
BLI_addtail(&sl->object_bases, base);
+
+ IDPropertyTemplate val = {0};
+ base->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
}
+
base->refcount++;
return base;
}
@@ -377,7 +296,16 @@ static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
BLI_freelistN(&lc->object_bases);
BLI_freelistN(&lc->overrides);
- layer_collection_engine_settings_free(lc);
+
+ if (lc->properties) {
+ IDP_FreeProperty(lc->properties);
+ MEM_freeN(lc->properties);
+ }
+
+ if (lc->properties_evaluated) {
+ IDP_FreeProperty(lc->properties_evaluated);
+ MEM_freeN(lc->properties_evaluated);
+ }
for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
layer_collection_free(sl, nlc);
@@ -450,7 +378,7 @@ int BKE_layer_collection_count(SceneLayer *sl)
/**
* Recursively get the index for a given collection
*/
-static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
+static int index_from_collection(ListBase *lb, const LayerCollection *lc, int *i)
{
for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) {
if (lcol == lc) {
@@ -470,19 +398,364 @@ static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
/**
* Return -1 if not found
*/
-int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc)
+int BKE_layer_collection_findindex(SceneLayer *sl, const LayerCollection *lc)
{
int i = 0;
return index_from_collection(&sl->layer_collections, lc, &i);
}
/**
+ * Lookup the listbase that contains \a lc.
+ */
+static ListBase *layer_collection_listbase_find(ListBase *lb, LayerCollection *lc)
+{
+ for (LayerCollection *lc_iter = lb->first; lc_iter; lc_iter = lc_iter->next) {
+ if (lc_iter == lc) {
+ return lb;
+ }
+
+ ListBase *lb_child_result;
+ if ((lb_child_result = layer_collection_listbase_find(&lc_iter->layer_collections, lc))) {
+ return lb_child_result;
+ }
+ }
+
+ return NULL;
+}
+
+#if 0
+/**
+ * Lookup the listbase that contains \a sc.
+ */
+static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *sc)
+{
+ for (SceneCollection *sc_iter = lb->first; sc_iter; sc_iter = sc_iter->next) {
+ if (sc_iter == sc) {
+ return lb;
+ }
+
+ ListBase *lb_child_result;
+ if ((lb_child_result = scene_collection_listbase_find(&sc_iter->scene_collections, sc))) {
+ return lb_child_result;
+ }
+ }
+
+ return NULL;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* Outliner drag and drop */
+
+/**
+ * Nest a LayerCollection into another one
+ * Both collections must be from the same SceneLayer, return true if succeded.
+ *
+ * The LayerCollection will effectively be moved into the
+ * new (nested) position. So all the settings, overrides, ... go with it, and
+ * if the collection was directly linked to the SceneLayer it's then unlinked.
+ *
+ * For the other SceneLayers we simply resync the tree, without changing directly
+ * linked collections (even if they link to the same SceneCollection)
+ *
+ * \param lc_src LayerCollection to nest into \a lc_dst
+ * \param lc_dst LayerCollection to have \a lc_src inserted into
+ */
+
+static void layer_collection_swap(
+ SceneLayer *sl, ListBase *lb_a, ListBase *lb_b,
+ LayerCollection *lc_a, LayerCollection *lc_b)
+{
+ if (lb_a == NULL) {
+ lb_a = layer_collection_listbase_find(&sl->layer_collections, lc_a);
+ }
+
+ if (lb_b == NULL) {
+ lb_b = layer_collection_listbase_find(&sl->layer_collections, lc_b);
+ }
+
+ BLI_assert(lb_a);
+ BLI_assert(lb_b);
+
+ BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b);
+}
+
+/**
+ * Move \a lc_src into \a lc_dst. Both have to be stored in \a sl.
+ * If \a lc_src is directly linked to the SceneLayer it's unlinked
+ */
+bool BKE_layer_collection_move_into(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc_src);
+ bool is_directly_linked = false;
+
+ if ((!sl) || (sl != BKE_scene_layer_find_from_collection(scene, lc_dst))) {
+ return false;
+ }
+
+ /* We can't nest the collection into itself */
+ if (lc_src->scene_collection == lc_dst->scene_collection) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->layer_collections.last == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->layer_collections.last;
+ layer_collection_swap(sl, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src);
+
+ if (BLI_findindex(&sl->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(sl, lc_swap);
+ }
+ return true;
+ }
+ else {
+ LayerCollection *lc_temp;
+ is_directly_linked = BLI_findindex(&sl->layer_collections, lc_src) != -1;
+
+ if (!is_directly_linked) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(sl, lc_src->scene_collection);
+ layer_collection_swap(sl, &sl->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_into(scene, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked) {
+ /* Swap back and remove */
+ layer_collection_swap(sl, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(sl, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = BLI_findptr(&lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection));
+ BLI_assert(lc_new);
+ layer_collection_swap(sl, &lc_dst->layer_collections, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&sl->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(sl, lc_new);
+ }
+
+ return true;
+}
+
+/**
+ * Move \a lc_src above \a lc_dst. Both have to be stored in \a sl.
+ * If \a lc_src is directly linked to the SceneLayer it's unlinked
+ */
+bool BKE_layer_collection_move_above(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc_src);
+ const bool is_directly_linked_src = BLI_findindex(&sl->layer_collections, lc_src) != -1;
+ const bool is_directly_linked_dst = BLI_findindex(&sl->layer_collections, lc_dst) != -1;
+
+ if ((!sl) || (sl != BKE_scene_layer_find_from_collection(scene, lc_dst))) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->prev == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->prev;
+ layer_collection_swap(sl, NULL, NULL, lc_dst->prev, lc_src);
+
+ if (BLI_findindex(&sl->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(sl, lc_swap);
+ }
+ return true;
+ }
+ /* We don't allow to move above/below a directly linked collection
+ * unless the source collection is also directly linked */
+ else if (is_directly_linked_dst) {
+ /* Both directly linked to the SceneLayer, just need to swap */
+ if (is_directly_linked_src) {
+ BLI_remlink(&sl->layer_collections, lc_src);
+ BLI_insertlinkbefore(&sl->layer_collections, lc_dst, lc_src);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ LayerCollection *lc_temp;
+
+ if (!is_directly_linked_src) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(sl, lc_src->scene_collection);
+ layer_collection_swap(sl, &sl->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_above(scene, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked_src) {
+ /* Swap back and remove */
+ layer_collection_swap(sl, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(sl, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = lc_dst->prev;
+ BLI_assert(lc_new);
+ layer_collection_swap(sl, NULL, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&sl->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(sl, lc_new);
+ }
+
+ return true;
+}
+
+/**
+ * Move \a lc_src below \a lc_dst. Both have to be stored in \a sl.
+ * If \a lc_src is directly linked to the SceneLayer it's unlinked
+ */
+bool BKE_layer_collection_move_below(const Scene *scene, LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc_src);
+ const bool is_directly_linked_src = BLI_findindex(&sl->layer_collections, lc_src) != -1;
+ const bool is_directly_linked_dst = BLI_findindex(&sl->layer_collections, lc_dst) != -1;
+
+ if ((!sl) || (sl != BKE_scene_layer_find_from_collection(scene, lc_dst))) {
+ return false;
+ }
+
+ /* Collection is already where we wanted it to be */
+ if (lc_dst->next == lc_src) {
+ return false;
+ }
+
+ /* Collection is already where we want it to be in the scene tree
+ * but we want to swap it in the layer tree still */
+ if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) {
+ LayerCollection *lc_swap = lc_dst->next;
+ layer_collection_swap(sl, NULL, NULL, lc_dst->next, lc_src);
+
+ if (BLI_findindex(&sl->layer_collections, lc_swap) != -1) {
+ BKE_collection_unlink(sl, lc_swap);
+ }
+ return true;
+ }
+ /* We don't allow to move above/below a directly linked collection
+ * unless the source collection is also directly linked */
+ else if (is_directly_linked_dst) {
+ /* Both directly linked to the SceneLayer, just need to swap */
+ if (is_directly_linked_src) {
+ BLI_remlink(&sl->layer_collections, lc_src);
+ BLI_insertlinkafter(&sl->layer_collections, lc_dst, lc_src);
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ LayerCollection *lc_temp;
+
+ if (!is_directly_linked_src) {
+ /* lc_src will be invalid after BKE_collection_move_into!
+ * so we swap it with lc_temp to preserve its settings */
+ lc_temp = BKE_collection_link(sl, lc_src->scene_collection);
+ layer_collection_swap(sl, &sl->layer_collections, NULL, lc_temp, lc_src);
+ }
+
+ if (!BKE_collection_move_below(scene, lc_dst->scene_collection, lc_src->scene_collection)) {
+ if (!is_directly_linked_src) {
+ /* Swap back and remove */
+ layer_collection_swap(sl, NULL, NULL, lc_temp, lc_src);
+ BKE_collection_unlink(sl, lc_temp);
+ }
+ return false;
+ }
+ }
+
+ LayerCollection *lc_new = lc_dst->next;
+ BLI_assert(lc_new);
+ layer_collection_swap(sl, NULL, NULL, lc_new, lc_src);
+
+ /* If it's directly linked, unlink it after the swap */
+ if (BLI_findindex(&sl->layer_collections, lc_new) != -1) {
+ BKE_collection_unlink(sl, lc_new);
+ }
+
+ return true;
+}
+
+static bool layer_collection_resync(SceneLayer *sl, LayerCollection *lc, const SceneCollection *sc)
+{
+ if (lc->scene_collection == sc) {
+ ListBase collections = {NULL};
+ BLI_movelisttolist(&collections, &lc->layer_collections);
+
+ for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
+ LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection));
+ if (lc_nested) {
+ BLI_remlink(&collections, lc_nested);
+ BLI_addtail(&lc->layer_collections, lc_nested);
+ }
+ else {
+ layer_collection_add(sl, lc, sc_nested);
+ }
+ }
+
+ for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) {
+ layer_collection_free(sl, lc_nested);
+ }
+ BLI_freelistN(&collections);
+
+ BLI_assert(BLI_listbase_count(&lc->layer_collections) ==
+ BLI_listbase_count(&sc->scene_collections));
+
+ return true;
+ }
+
+ for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) {
+ if (layer_collection_resync(sl, lc_nested, sc)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Update the scene layers so that any LayerCollection that points
+ * to \a sc is re-synced again
+ */
+void BKE_layer_collection_resync(const Scene *scene, const SceneCollection *sc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_resync(sl, lc, sc);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
* Link a collection to a renderlayer
* The collection needs to be created separately
*/
LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
{
- LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc);
+ LayerCollection *lc = layer_collection_add(sl, NULL, sc);
sl->active_collection = BKE_layer_collection_findindex(sl, lc);
return lc;
}
@@ -494,9 +767,6 @@ LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
{
BKE_layer_collection_free(sl, lc);
- BKE_scene_layer_base_flag_recalculate(sl);
- BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
-
BLI_remlink(&sl->layer_collections, lc);
MEM_freeN(lc);
sl->active_collection = 0;
@@ -514,9 +784,6 @@ static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Obj
}
BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
-
- BKE_scene_layer_base_flag_recalculate(sl);
- BKE_scene_layer_engine_settings_object_recalculate(sl, ob);
}
static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob)
@@ -544,30 +811,39 @@ static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, Scene
layer_collection_objects_populate(sl, lc, &sc->filter_objects);
for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
- layer_collection_add(sl, &lc->layer_collections, nsc);
+ layer_collection_add(sl, lc, nsc);
}
}
-static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
+static LayerCollection *layer_collection_add(SceneLayer *sl, LayerCollection *parent, SceneCollection *sc)
{
+ IDPropertyTemplate val = {0};
LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
- BLI_addtail(lb, lc);
lc->scene_collection = sc;
- lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
+ lc->flag = COLLECTION_VISIBLE | COLLECTION_SELECTABLE;
+
+ lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(lc->properties, false);
+
+ if (parent != NULL) {
+ BLI_addtail(&parent->layer_collections, lc);
+ }
+ else {
+ BLI_addtail(&sl->layer_collections, lc);
+ }
- layer_collection_create_engine_settings(lc);
layer_collection_populate(sl, lc, sc);
+
return lc;
}
-
/* ---------------------------------------------------------------------- */
/**
* See if render layer has the scene collection linked directly, or indirectly (nested)
*/
-bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
+bool BKE_scene_layer_has_collection(SceneLayer *sl, const SceneCollection *sc)
{
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
@@ -619,7 +895,7 @@ void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
if (lc_parent) {
- layer_collection_add(sl, &lc_parent->layer_collections, sc);
+ layer_collection_add(sl, lc_parent, sc);
}
}
}
@@ -628,7 +904,7 @@ void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc
/**
* Add a corresponding ObjectBase to all the equivalent LayerCollection
*/
-void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
+void BKE_layer_sync_object_link(const Scene *scene, SceneCollection *sc, Object *ob)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
@@ -644,7 +920,7 @@ void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
* Remove the equivalent object base to all layers that have this collection
* also remove all reference to ob in the filter_objects
*/
-void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
+void BKE_layer_sync_object_unlink(const Scene *scene, SceneCollection *sc, Object *ob)
{
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
@@ -653,8 +929,6 @@ void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
layer_collection_object_remove(sl, found, ob);
}
}
- BKE_scene_layer_base_flag_recalculate(sl);
- BKE_scene_layer_engine_settings_object_recalculate(sl, ob);
}
}
@@ -683,14 +957,24 @@ typedef struct CollectionEngineSettingsCB_Type {
} CollectionEngineSettingsCB_Type;
+static void create_engine_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type)
+{
+ if (collection_engine_get(scene->collection_properties, COLLECTION_MODE_NONE, ces_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(ces_type, true);
+ IDP_AddToGroup(scene->collection_properties, props);
+}
+
static void create_engine_settings_layer_collection(LayerCollection *lc, CollectionEngineSettingsCB_Type *ces_type)
{
- if (BKE_layer_collection_engine_get(lc, ces_type->name)) {
+ if (BKE_layer_collection_engine_get(lc, COLLECTION_MODE_NONE, ces_type->name)) {
return;
}
- CollectionEngineSettings *ces = collection_engine_settings_create(ces_type);
- BLI_addtail(&lc->engine_settings, ces);
+ IDProperty *props = collection_engine_settings_create(ces_type, false);
+ IDP_AddToGroup(lc->properties, props);
for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
create_engine_settings_layer_collection(lcn, ces_type);
@@ -699,6 +983,9 @@ static void create_engine_settings_layer_collection(LayerCollection *lc, Collect
static void create_engines_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type)
{
+ /* populate the scene with the new settings */
+ create_engine_settings_scene(scene, ces_type);
+
for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
create_engine_settings_layer_collection(lc, ces_type);
@@ -712,7 +999,8 @@ void BKE_layer_collection_engine_settings_callback_register(
CollectionEngineSettingsCB_Type *ces_type;
/* cleanup in case it existed */
- ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+ ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name,
+ offsetof(CollectionEngineSettingsCB_Type, name));
if (ces_type) {
BLI_remlink(&R_engines_settings_callbacks, ces_type);
@@ -737,257 +1025,214 @@ void BKE_layer_collection_engine_settings_callback_free(void)
BLI_freelistN(&R_engines_settings_callbacks);
}
-static CollectionEngineSettings *collection_engine_settings_create(CollectionEngineSettingsCB_Type *ces_type)
-{
- /* create callback data */
- CollectionEngineSettings *ces = MEM_callocN(sizeof(CollectionEngineSettings), "Collection Engine Settings");
- BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
-
- /* call callback */
- ces_type->callback(NULL, ces);
-
- return ces;
-}
-
/**
- * Initialize a CollectionEngineSettings
+ * Create a root IDProperty for this engine
*
- * Usually we would pass LayerCollection->engine_settings
- * But depsgraph uses this for Object->collection_settings
+ * \param populate whether we want to pre-fill the collection with the default properties
*/
-CollectionEngineSettings *BKE_layer_collection_engine_settings_create(const char *engine_name)
+static IDProperty *collection_engine_settings_create(CollectionEngineSettingsCB_Type *ces_type, const bool populate)
{
- CollectionEngineSettingsCB_Type *ces_type;
- ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
- BLI_assert(ces_type);
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, ces_type->name);
+ props->subtype = IDP_GROUP_SUB_ENGINE_RENDER;
+
+ /* properties */
+ if (populate) {
+ ces_type->callback(NULL, props);
+ }
- CollectionEngineSettings *ces = collection_engine_settings_create(ces_type);
- return ces;
+ return props;
}
-/**
- * Free the CollectionEngineSettings
- */
-void BKE_layer_collection_engine_settings_free(CollectionEngineSettings *ces)
+static void layer_collection_create_mode_settings_object(IDProperty *root, const bool populate)
{
- BLI_freelistN(&ces->properties);
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "ObjectMode");
+ props->subtype = IDP_GROUP_SUB_MODE_OBJECT;
+
+ /* properties */
+ if (populate) {
+ OBJECT_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
}
-static void layer_collection_engine_settings_free(LayerCollection *lc)
+static void layer_collection_create_mode_settings_edit(IDProperty *root, const bool populate)
{
- for (CollectionEngineSettings *ces = lc->engine_settings.first; ces; ces = ces->next) {
- BKE_layer_collection_engine_settings_free(ces);
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "EditMode");
+ props->subtype = IDP_GROUP_SUB_MODE_EDIT;
+
+ /* properties */
+ if (populate) {
+ EDIT_MESH_collection_settings_create(props);
}
- BLI_freelistN(&lc->engine_settings);
+
+ IDP_AddToGroup(root, props);
}
-/**
- * Initialize the render settings for a single LayerCollection
- */
-static void layer_collection_create_engine_settings(LayerCollection *lc)
+static void collection_create_render_settings(IDProperty *root, const bool populate)
{
CollectionEngineSettingsCB_Type *ces_type;
for (ces_type = R_engines_settings_callbacks.first; ces_type; ces_type = ces_type->next) {
- create_engine_settings_layer_collection(lc, ces_type);
+ IDProperty *props = collection_engine_settings_create(ces_type, populate);
+ IDP_AddToGroup(root, props);
}
}
-/**
- * Return layer collection engine settings for specified engine
- */
-CollectionEngineSettings *BKE_layer_collection_engine_get(LayerCollection *lc, const char *engine_name)
+static void collection_create_mode_settings(IDProperty *root, const bool populate)
{
- CollectionEngineSettings *ces;
- ces = BLI_findstring(&lc->engine_settings, engine_name, offsetof(CollectionEngineSettings, name));
- return ces;
+ /* XXX TODO: put all those engines in the R_engines_settings_callbacks
+ * and have IDP_AddToGroup outside the callbacks */
+ layer_collection_create_mode_settings_object(root, populate);
+ layer_collection_create_mode_settings_edit(root, populate);
}
-/* ---------------------------------------------------------------------- */
-/* Engine Settings Properties */
-
-void BKE_collection_engine_property_add_float(CollectionEngineSettings *ces, const char *name, float value)
+static int idproperty_group_subtype(const int mode_type)
{
- CollectionEnginePropertyFloat *prop;
- prop = MEM_callocN(sizeof(CollectionEnginePropertyFloat), "collection engine settings float");
- prop->data.type = COLLECTION_PROP_TYPE_FLOAT;
- BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
- prop->value = value;
- BLI_addtail(&ces->properties, prop);
-}
+ int idgroup_type;
-void BKE_collection_engine_property_add_int(CollectionEngineSettings *ces, const char *name, int value)
-{
- CollectionEnginePropertyInt *prop;
- prop = MEM_callocN(sizeof(CollectionEnginePropertyInt), "collection engine settings int");
- prop->data.type = COLLECTION_PROP_TYPE_INT;
- BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
- prop->value = value;
- BLI_addtail(&ces->properties, prop);
+ switch (mode_type) {
+ case COLLECTION_MODE_OBJECT:
+ idgroup_type = IDP_GROUP_SUB_MODE_OBJECT;
+ break;
+ case COLLECTION_MODE_EDIT:
+ idgroup_type = IDP_GROUP_SUB_MODE_EDIT;
+ break;
+ default:
+ case COLLECTION_MODE_NONE:
+ return IDP_GROUP_SUB_ENGINE_RENDER;
+ break;
+ }
+
+ return idgroup_type;
}
-CollectionEngineProperty *BKE_collection_engine_property_get(CollectionEngineSettings *ces, const char *name)
+/**
+ * Return collection enginne settings for either Object s of LayerCollection s
+ */
+static IDProperty *collection_engine_get(
+ IDProperty *root, const int type, const char *engine_name)
{
- return BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+ const int subtype = idproperty_group_subtype(type);
+
+ if (subtype == IDP_GROUP_SUB_ENGINE_RENDER) {
+ return IDP_GetPropertyFromGroup(root, engine_name);
+ }
+ else {
+ IDProperty *prop;
+ for (prop = root->data.group.first; prop; prop = prop->next) {
+ if (prop->subtype == subtype) {
+ return prop;
+ }
+ }
+ }
+
+ BLI_assert(false);
+ return NULL;
}
-int BKE_collection_engine_property_value_get_int(CollectionEngineSettings *ces, const char *name)
+/**
+ * Return collection engine settings from Object for specified engine of mode
+ */
+IDProperty *BKE_object_collection_engine_get(Object *ob, const int type, const char *engine_name)
{
- CollectionEnginePropertyInt *prop;
- prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
- return prop->value;
+ return collection_engine_get(ob->base_collection_properties, type, engine_name);
}
-
-float BKE_collection_engine_property_value_get_float(CollectionEngineSettings *ces, const char *name)
+/**
+ * Return layer collection engine settings for specified engine
+ */
+IDProperty *BKE_layer_collection_engine_get(LayerCollection *lc, const int type, const char *engine_name)
{
- CollectionEnginePropertyFloat *prop;
- prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
- return prop->value;
+ return collection_engine_get(lc->properties, type, engine_name);
}
-void BKE_collection_engine_property_value_set_int(CollectionEngineSettings *ces, const char *name, int value)
+/* ---------------------------------------------------------------------- */
+/* Engine Settings Properties */
+
+void BKE_collection_engine_property_add_float(IDProperty *props, const char *name, float value)
{
- CollectionEnginePropertyInt *prop;
- prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
- prop->value = value;
- prop->data.flag |= COLLECTION_PROP_USE;
+ IDPropertyTemplate val = {0};
+ val.f = value;
+ IDP_AddToGroup(props, IDP_New(IDP_FLOAT, &val, name));
}
-void BKE_collection_engine_property_value_set_float(CollectionEngineSettings *ces, const char *name, float value)
+void BKE_collection_engine_property_add_int(IDProperty *props, const char *name, int value)
{
- CollectionEnginePropertyFloat *prop;
- prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
- prop->value = value;
- prop->data.flag |= COLLECTION_PROP_USE;
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
}
-bool BKE_collection_engine_property_use_get(CollectionEngineSettings *ces, const char *name)
+void BKE_collection_engine_property_add_bool(IDProperty *props, const char *name, bool value)
{
- CollectionEngineProperty *prop;
- prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
- return ((prop->flag & COLLECTION_PROP_USE) != 0);
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
}
-void BKE_collection_engine_property_use_set(CollectionEngineSettings *ces, const char *name, bool value)
+int BKE_collection_engine_property_value_get_int(IDProperty *props, const char *name)
{
- CollectionEngineProperty *prop;
- prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
-
- if (value) {
- prop->flag |= COLLECTION_PROP_USE;
- }
- else {
- prop->flag &= ~COLLECTION_PROP_USE;
- }
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? idprop->data.val : 0;
}
-/* Engine Settings recalculate */
-
-static void collection_engine_settings_init(CollectionEngineSettings *ces, const char *engine_name)
+float BKE_collection_engine_property_value_get_float(IDProperty *props, const char *name)
{
- CollectionEngineSettingsCB_Type *ces_type;
- ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
-
- BLI_listbase_clear(&ces->properties);
- BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
-
- /* call callback */
- ces_type->callback(NULL, ces);
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? *((float *)&idprop->data.val) : 0.0f;
}
-static void collection_engine_settings_copy(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src)
+bool BKE_collection_engine_property_value_get_bool(IDProperty *props, const char *name)
{
- BLI_strncpy_utf8(ces_dst->name, ces_src->name, sizeof(ces_dst->name));
- BLI_freelistN(&ces_dst->properties);
-
- for (CollectionEngineProperty *prop = ces_src->properties.first; prop; prop = prop->next) {
- CollectionEngineProperty *prop_new = MEM_dupallocN(prop);
- BLI_addtail(&ces_dst->properties, prop_new);
- }
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? idprop->data.val : 0;
}
-/**
- * Set a value from a CollectionProperty to another
- */
-static void collection_engine_property_set (CollectionEngineProperty *prop_dst, CollectionEngineProperty *prop_src){
- if ((prop_src->flag & COLLECTION_PROP_USE) != 0) {
- /* mark the property as used, so the engine knows if the value was ever set*/
- prop_dst->flag |= COLLECTION_PROP_USE;
- switch (prop_src->type) {
- case COLLECTION_PROP_TYPE_FLOAT:
- ((CollectionEnginePropertyFloat *)prop_dst)->value = ((CollectionEnginePropertyFloat *)prop_src)->value;
- break;
- case COLLECTION_PROP_TYPE_INT:
- ((CollectionEnginePropertyInt *)prop_dst)->value = ((CollectionEnginePropertyInt *)prop_src)->value;
- break;
- default:
- BLI_assert(false);
- break;
- }
- }
+void BKE_collection_engine_property_value_set_int(IDProperty *props, const char *name, int value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ idprop->data.val = value;
}
-static void collection_engine_settings_merge(CollectionEngineSettings *ces_dst, CollectionEngineSettings *ces_src)
+void BKE_collection_engine_property_value_set_float(IDProperty *props, const char *name, float value)
{
- CollectionEngineProperty *prop_src, *prop_dst;
-
- prop_dst = ces_dst->properties.first;
- for (prop_src = ces_src->properties.first; prop_src; prop_src = prop_src->next, prop_dst = prop_dst->next) {
- collection_engine_property_set(prop_dst, prop_src);
- }
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ *(float *)&idprop->data.val = value;
}
-static void layer_collection_engine_settings_update(
- LayerCollection *lc, CollectionEngineSettings *ces_parent,
- Base *base, CollectionEngineSettings *ces_ob)
+void BKE_collection_engine_property_value_set_bool(IDProperty *props, const char *name, bool value)
{
- if ((lc->flag & COLLECTION_VISIBLE) == 0) {
- return;
- }
-
- CollectionEngineSettings ces = {NULL};
- collection_engine_settings_copy(&ces, ces_parent);
-
- CollectionEngineSettings *ces_lc = BKE_layer_collection_engine_get(lc, ces.name);
- collection_engine_settings_merge(&ces, ces_lc);
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ idprop->data.val = value;
+}
- if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)) != NULL) {
- collection_engine_settings_merge(ces_ob, &ces);
- }
+/* Engine Settings recalculate */
- /* do it recursively */
- for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
- layer_collection_engine_settings_update(lcn, &ces, base, ces_ob);
- }
+/* get all the default settings defined in scene and merge them here */
+static void collection_engine_settings_init(IDProperty *root, const bool populate)
+{
+ /* render engines */
+ collection_create_render_settings(root, populate);
- BKE_layer_collection_engine_settings_free(&ces);
+ /* mode engines */
+ collection_create_mode_settings(root, populate);
}
/**
- * Update the collection settings pointer allocated in the object
- * This is to be flushed from the Depsgraph
+ * Initialize the render setings
+ * It's used mainly for scenes
*/
-static void scene_layer_engine_settings_update(SceneLayer *sl, Object *ob, const char *engine_name)
+void BKE_layer_collection_engine_settings_create(IDProperty *root)
{
- Base *base = BKE_scene_layer_base_find(sl, ob);
- CollectionEngineSettings ces_layer = {NULL}, *ces_ob;
-
- collection_engine_settings_init(&ces_layer, engine_name);
-
- if (ob->collection_settings) {
- BKE_layer_collection_engine_settings_free(ob->collection_settings);
- MEM_freeN(ob->collection_settings);
- }
-
- CollectionEngineSettingsCB_Type *ces_type;
- ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
- ces_ob = collection_engine_settings_create(ces_type);
-
- for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
- layer_collection_engine_settings_update(lc, &ces_layer, base, ces_ob);
- }
-
- BKE_layer_collection_engine_settings_free(&ces_layer);
- ob->collection_settings = ces_ob;
+ collection_engine_settings_init(root, true);
}
/* ---------------------------------------------------------------------- */
@@ -1094,3 +1339,100 @@ void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
{
/* do nothing */
}
+
+/* Evaluation */
+
+/**
+ * Reset props
+ *
+ * If props_ref is pasted, copy props from it
+ */
+static void idproperty_reset(IDProperty **props, IDProperty *props_ref)
+{
+ IDPropertyTemplate val = {0};
+
+ if (*props) {
+ IDP_FreeProperty(*props);
+ MEM_freeN(*props);
+ }
+ *props = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+
+ if (props_ref) {
+ IDP_MergeGroup(*props, props_ref, true);
+ }
+}
+
+void BKE_layer_eval_layer_collection_pre(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene, SceneLayer *scene_layer)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, scene_layer->name);
+ for (Base *base = scene_layer->object_bases.first; base != NULL; base = base->next) {
+ base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED);
+ idproperty_reset(&base->collection_properties, scene->collection_properties);
+ }
+
+ /* TODO(sergey): Is it always required? */
+ scene_layer->flag |= SCENE_LAYER_ENGINE_DIRTY;
+}
+
+void BKE_layer_eval_layer_collection(EvaluationContext *UNUSED(eval_ctx),
+ Scene *scene,
+ LayerCollection *layer_collection,
+ LayerCollection *parent_layer_collection)
+{
+ DEBUG_PRINT("%s on %s, parent %s\n",
+ __func__,
+ layer_collection->scene_collection->name,
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE");
+
+ /* visibility */
+ layer_collection->flag_evaluated = layer_collection->flag;
+ bool is_visible = (layer_collection->flag & COLLECTION_VISIBLE) != 0;
+ bool is_selectable = is_visible && ((layer_collection->flag & COLLECTION_SELECTABLE) != 0);
+
+ if (parent_layer_collection != NULL) {
+ is_visible &= (parent_layer_collection->flag_evaluated & COLLECTION_VISIBLE) != 0;
+ is_selectable &= (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0;
+ layer_collection->flag_evaluated &= parent_layer_collection->flag_evaluated;
+ }
+
+ /* overrides */
+ if (parent_layer_collection != NULL) {
+ idproperty_reset(&layer_collection->properties_evaluated, parent_layer_collection->properties_evaluated);
+ }
+ else if (layer_collection->prev != NULL) {
+ idproperty_reset(&layer_collection->properties_evaluated, NULL);
+ }
+ else {
+ idproperty_reset(&layer_collection->properties_evaluated, scene->collection_properties);
+ }
+
+ if (is_visible) {
+ IDP_MergeGroup(layer_collection->properties_evaluated, layer_collection->properties, true);
+ }
+
+ for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) {
+ Base *base = link->data;
+
+ if (is_visible) {
+ IDP_SyncGroupValues(base->collection_properties, layer_collection->properties_evaluated);
+ base->flag |= BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+}
+
+void BKE_layer_eval_layer_collection_post(EvaluationContext *UNUSED(eval_ctx),
+ SceneLayer *scene_layer)
+{
+ DEBUG_PRINT("%s on %s\n", __func__, scene_layer->name);
+ /* if base is not selectabled, clear select */
+ for (Base *base = scene_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 2398c6724ed..c95d13b7668 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -1863,7 +1863,7 @@ void BKE_library_make_local(
/* Special case for objects because we don't want proxy pointers to be
* cleared yet. This will happen down the road in this function.
*/
- BKE_object_make_local_ex(bmain, (Object*)id, true, false);
+ BKE_object_make_local_ex(bmain, (Object *)id, true, false);
}
else {
id_make_local(bmain, id, false, true);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index a071b3202be..c9853f791ce 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -416,7 +416,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER);
}
- SceneCollection *sc;
FOREACH_SCENE_COLLECTION(scene, sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 9946d1cc81f..7f290590942 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -180,6 +180,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
* on the other hand since they get reset to lib data on file open/reload it is indirect too...
* Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id->name) == ID_OB);
+ const bool is_obj_proxy = (is_obj && (((Object *)id)->proxy || ((Object *)id)->proxy_group));
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
(id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
@@ -232,7 +233,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
/* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET) are assumed to be set as needed,
* that extra user is processed in final handling... */
}
- if (!is_indirect) {
+ if (!is_indirect || is_obj_proxy) {
id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
}
@@ -289,7 +290,6 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- Object *ob_iter;
FOREACH_SCENE_OBJECT(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 435504859a4..6cab8945779 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -111,12 +111,6 @@ void BKE_material_free(Material *ma)
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
-
- for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) {
- if (mes->data)
- MEM_SAFE_FREE(mes->data);
- }
- BLI_freelistN(&ma->engines_settings);
}
void BKE_material_init(Material *ma)
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 134173580ae..0f0d84cc87d 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -39,7 +39,9 @@
#include "BLI_utildefines.h"
#include "BLI_math.h"
+#include "BLI_linklist.h"
#include "BLI_listbase.h"
+#include "BLI_memarena.h"
#include "BLI_edgehash.h"
#include "BLI_string.h"
@@ -67,6 +69,11 @@
#include "DEG_depsgraph.h"
+/* Define for cases when you want extra validation of mesh
+ * after certain modifications.
+ */
+// #undef VALIDATE_MESH
+
enum {
MESHCMP_DVERT_WEIGHTMISMATCH = 1,
MESHCMP_DVERT_GROUPMISMATCH,
@@ -2052,7 +2059,7 @@ void BKE_mesh_mselect_active_set(Mesh *me, int index, int type)
(me->mselect[me->totselect - 1].type == type));
}
-void BKE_mesh_calc_normals_split(Mesh *mesh)
+void BKE_mesh_calc_normals_split_ex(Mesh *mesh, MLoopNorSpaceArray *r_lnors_spacearr)
{
float (*r_loopnors)[3];
float (*polynors)[3];
@@ -2087,113 +2094,339 @@ void BKE_mesh_calc_normals_split(Mesh *mesh)
BKE_mesh_normals_loop_split(
mesh->mvert, mesh->totvert, mesh->medge, mesh->totedge,
mesh->mloop, r_loopnors, mesh->totloop, mesh->mpoly, (const float (*)[3])polynors, mesh->totpoly,
- (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, NULL, clnors, NULL);
+ (mesh->flag & ME_AUTOSMOOTH) != 0, mesh->smoothresh, r_lnors_spacearr, clnors, NULL);
if (free_polynors) {
MEM_freeN(polynors);
}
}
-/* Spli faces based on the edge angle.
- * Matches behavior of face splitting in render engines.
- */
-void BKE_mesh_split_faces(Mesh *mesh)
+void BKE_mesh_calc_normals_split(Mesh *mesh)
{
- const int num_verts = mesh->totvert;
- const int num_edges = mesh->totedge;
- const int num_polys = mesh->totpoly;
+ BKE_mesh_calc_normals_split_ex(mesh, NULL);
+}
+
+/* Split faces helper functions. */
+
+typedef struct SplitFaceNewVert {
+ struct SplitFaceNewVert *next;
+ int new_index;
+ int orig_index;
+ float *vnor;
+} SplitFaceNewVert;
+
+typedef struct SplitFaceNewEdge {
+ struct SplitFaceNewEdge *next;
+ int new_index;
+ int orig_index;
+ int v1;
+ int v2;
+} SplitFaceNewEdge;
+
+/* Detect needed new vertices, and update accordingly loops' vertex indices.
+ * WARNING! Leaves mesh in invalid state. */
+static int split_faces_prepare_new_verts(
+ const Mesh *mesh, MLoopNorSpaceArray *lnors_spacearr, SplitFaceNewVert **new_verts, MemArena *memarena,
+ bool *r_need_vnors_recalc)
+{
+ /* Note: if lnors_spacearr is NULL, ther is no autosmooth handling, and we only split out flat polys. */
+ const int num_loops = mesh->totloop;
+ int num_verts = mesh->totvert;
MVert *mvert = mesh->mvert;
- MEdge *medge = mesh->medge;
MLoop *mloop = mesh->mloop;
- MPoly *mpoly = mesh->mpoly;
- float (*lnors)[3];
- int poly, num_new_verts = 0;
- if ((mesh->flag & ME_AUTOSMOOTH) == 0) {
- return;
- }
- BKE_mesh_tessface_clear(mesh);
- /* Compute loop normals if needed. */
- if (!CustomData_has_layer(&mesh->ldata, CD_NORMAL)) {
- BKE_mesh_calc_normals_split(mesh);
- }
- lnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
- /* Count number of vertices to be split. */
- for (poly = 0; poly < num_polys; poly++) {
- MPoly *mp = &mpoly[poly];
- int loop;
- for (loop = 0; loop < mp->totloop; loop++) {
- MLoop *ml = &mloop[mp->loopstart + loop];
- MVert *mv = &mvert[ml->v];
- float vn[3];
- normal_short_to_float_v3(vn, mv->no);
- if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
- num_new_verts++;
+
+ BLI_bitmap *verts_used = BLI_BITMAP_NEW(num_verts, __func__);
+
+ if (lnors_spacearr) {
+ BLI_bitmap *done_loops = BLI_BITMAP_NEW(num_loops, __func__);
+
+ MLoop *ml = mloop;
+ MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
+ for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
+ if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
+ const int vert_idx = ml->v;
+ const bool vert_used = BLI_BITMAP_TEST_BOOL(verts_used, vert_idx);
+ /* If vert is already used by another smooth fan, we need a new vert for this one. */
+ const int new_vert_idx = vert_used ? num_verts++ : vert_idx;
+
+ BLI_assert(*lnor_space);
+
+ if ((*lnor_space)->loops) {
+ for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
+ const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
+ BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
+ if (vert_used) {
+ mloop[ml_fan_idx].v = new_vert_idx;
+ }
+ }
+ }
+ else {
+ /* Single loop in this fan... */
+ BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ if (vert_used) {
+ ml->v = new_vert_idx;
+ }
+ }
+
+ if (!vert_used) {
+ BLI_BITMAP_ENABLE(verts_used, vert_idx);
+ /* We need to update that vertex's normal here, we won't go over it again. */
+ /* This is important! *DO NOT* set vnor to final computed lnor, vnor should always be defined to
+ * 'automatic normal' value computed from its polys, not some custom normal.
+ * Fortunately, that's the loop normal space's 'lnor' reference vector. ;) */
+ normal_float_to_short_v3(mvert[vert_idx].no, (*lnor_space)->vec_lnor);
+ }
+ else {
+ /* Add new vert to list. */
+ SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
+ new_vert->orig_index = vert_idx;
+ new_vert->new_index = new_vert_idx;
+ new_vert->vnor = (*lnor_space)->vec_lnor; /* See note above. */
+ new_vert->next = *new_verts;
+ *new_verts = new_vert;
+ }
}
}
+
+ MEM_freeN(done_loops);
}
- if (num_new_verts == 0) {
- /* No new vertices are to be added, can do early exit. */
- return;
- }
- /* Reallocate all vert and edge related data. */
- mesh->totvert += num_new_verts;
- mesh->totedge += 2 * num_new_verts;
- CustomData_realloc(&mesh->vdata, mesh->totvert);
- CustomData_realloc(&mesh->edata, mesh->totedge);
- /* Update pointers to a newly allocated memory. */
- BKE_mesh_update_customdata_pointers(mesh, false);
- mvert = mesh->mvert;
- medge = mesh->medge;
- /* Perform actual vertex split. */
- num_new_verts = 0;
- for (poly = 0; poly < num_polys; poly++) {
- MPoly *mp = &mpoly[poly];
- int loop;
- for (loop = 0; loop < mp->totloop; loop++) {
- int poly_loop = mp->loopstart + loop;
- MLoop *ml = &mloop[poly_loop];
- MVert *mv = &mvert[ml->v];
- float vn[3];
- normal_short_to_float_v3(vn, mv->no);
- if (!equals_v3v3(vn, lnors[mp->loopstart + loop])) {
- int poly_loop_prev = mp->loopstart + (loop + mp->totloop - 1) % mp->totloop;
- MLoop *ml_prev = &mloop[poly_loop_prev];
- int new_edge_prev, new_edge;
- /* Cretae new vertex. */
- int new_vert = num_verts + num_new_verts;
- CustomData_copy_data(&mesh->vdata, &mesh->vdata,
- ml->v, new_vert, 1);
- normal_float_to_short_v3(mvert[new_vert].no,
- lnors[poly_loop]);
- /* Create new edges. */
- new_edge_prev = num_edges + 2 * num_new_verts;
- new_edge = num_edges + 2 * num_new_verts + 1;
- CustomData_copy_data(&mesh->edata, &mesh->edata,
- ml_prev->e, new_edge_prev, 1);
- CustomData_copy_data(&mesh->edata, &mesh->edata,
- ml->e, new_edge, 1);
- if (medge[new_edge_prev].v1 == ml->v) {
- medge[new_edge_prev].v1 = new_vert;
+ else {
+ /* No loop normal spaces available, we only split out flat polys. */
+ const int num_polys = mesh->totpoly;
+ const MPoly *mpoly = mesh->mpoly;
+
+ /* We do that in two loops, to keep original edges/verts to smooth polys preferencially. */
+ const MPoly *mp = mpoly;
+ for (int i = 0; i < num_polys; i++, mp++) {
+ if (mp->flag & ME_SMOOTH) {
+ const MLoop *ml = &mloop[mp->loopstart];
+ for (int j = 0; j < mp->totloop; j++, ml++) {
+ /* Just mark the vertex as used/reserved, that way neighbor flat polys, if any,
+ * will have to create their own. */
+ BLI_BITMAP_ENABLE(verts_used, ml->v);
}
- else {
- medge[new_edge_prev].v2 = new_vert;
+ }
+ }
+
+ mp = mpoly;
+ for (int i = 0; i < num_polys; i++, mp++) {
+ if (!(mp->flag & ME_SMOOTH)) {
+ MLoop *ml = &mloop[mp->loopstart];
+ for (int j = 0; j < mp->totloop; j++, ml++) {
+ const int vert_idx = ml->v;
+
+ if (BLI_BITMAP_TEST(verts_used, vert_idx)) {
+ /* Add new vert to list. */
+ const int new_vert_idx = num_verts++;
+ ml->v = new_vert_idx;
+
+ SplitFaceNewVert *new_vert = BLI_memarena_alloc(memarena, sizeof(*new_vert));
+ new_vert->orig_index = vert_idx;
+ new_vert->new_index = new_vert_idx;
+ new_vert->vnor = NULL; /* See note below about normals. */
+ new_vert->next = *new_verts;
+ *new_verts = new_vert;
+ }
+ else {
+ BLI_BITMAP_ENABLE(verts_used, vert_idx);
+ }
}
- if (medge[new_edge].v1 == ml->v) {
- medge[new_edge].v1 = new_vert;
+ /* Note: there is no way to get new normals for smooth vertices here (and we don't have direct access
+ * to poly normals either for flat ones), so we'll have to recompute all vnors at the end... */
+ *r_need_vnors_recalc = true;
+ }
+ }
+ }
+
+ MEM_freeN(verts_used);
+
+ return num_verts - mesh->totvert;
+}
+
+/* Detect needed new edges, and update accordingly loops' edge indices.
+ * WARNING! Leaves mesh in invalid state. */
+static int split_faces_prepare_new_edges(
+ const Mesh *mesh, SplitFaceNewEdge **new_edges, MemArena *memarena)
+{
+ const int num_polys = mesh->totpoly;
+ int num_edges = mesh->totedge;
+ MEdge *medge = mesh->medge;
+ MLoop *mloop = mesh->mloop;
+ const MPoly *mpoly = mesh->mpoly;
+
+ BLI_bitmap *edges_used = BLI_BITMAP_NEW(num_edges, __func__);
+ EdgeHash *edges_hash = BLI_edgehash_new_ex(__func__, num_edges);
+
+ const MPoly *mp = mpoly;
+ for (int poly_idx = 0; poly_idx < num_polys; poly_idx++, mp++) {
+ MLoop *ml_prev = &mloop[mp->loopstart + mp->totloop - 1];
+ MLoop *ml = &mloop[mp->loopstart];
+ for (int loop_idx = 0; loop_idx < mp->totloop; loop_idx++, ml++) {
+ void **eval;
+ if (!BLI_edgehash_ensure_p(edges_hash, ml_prev->v, ml->v, &eval)) {
+ const int edge_idx = ml_prev->e;
+
+ /* That edge has not been encountered yet, define it. */
+ if (BLI_BITMAP_TEST(edges_used, edge_idx)) {
+ /* Original edge has already been used, we need to define a new one. */
+ const int new_edge_idx = num_edges++;
+ *eval = SET_INT_IN_POINTER(new_edge_idx);
+ ml_prev->e = new_edge_idx;
+
+ SplitFaceNewEdge *new_edge = BLI_memarena_alloc(memarena, sizeof(*new_edge));
+ new_edge->orig_index = edge_idx;
+ new_edge->new_index = new_edge_idx;
+ new_edge->v1 = ml_prev->v;
+ new_edge->v2 = ml->v;
+ new_edge->next = *new_edges;
+ *new_edges = new_edge;
}
else {
- medge[new_edge].v2 = new_vert;
+ /* We can re-use original edge. */
+ medge[edge_idx].v1 = ml_prev->v;
+ medge[edge_idx].v2 = ml->v;
+ *eval = SET_INT_IN_POINTER(edge_idx);
+ BLI_BITMAP_ENABLE(edges_used, edge_idx);
}
-
- ml->v = new_vert;
- ml_prev->e = new_edge_prev;
- ml->e = new_edge;
- num_new_verts++;
}
+ else {
+ /* Edge already known, just update loop's edge index. */
+ ml_prev->e = GET_INT_FROM_POINTER(*eval);
+ }
+
+ ml_prev = ml;
+ }
+ }
+
+ MEM_freeN(edges_used);
+ BLI_edgehash_free(edges_hash, NULL);
+
+ return num_edges - mesh->totedge;
+}
+
+/* Perform actual split of vertices. */
+static void split_faces_split_new_verts(
+ Mesh *mesh, SplitFaceNewVert *new_verts, const int num_new_verts)
+{
+ const int num_verts = mesh->totvert - num_new_verts;
+ MVert *mvert = mesh->mvert;
+
+ /* Remember new_verts is a single linklist, so its items are in reversed order... */
+ MVert *new_mv = &mvert[mesh->totvert - 1];
+ for (int i = mesh->totvert - 1; i >= num_verts ; i--, new_mv--, new_verts = new_verts->next) {
+ BLI_assert(new_verts->new_index == i);
+ BLI_assert(new_verts->new_index != new_verts->orig_index);
+ CustomData_copy_data(&mesh->vdata, &mesh->vdata, new_verts->orig_index, i, 1);
+ if (new_verts->vnor) {
+ normal_float_to_short_v3(new_mv->no, new_verts->vnor);
}
}
}
+/* Perform actual split of edges. */
+static void split_faces_split_new_edges(
+ Mesh *mesh, SplitFaceNewEdge *new_edges, const int num_new_edges)
+{
+ const int num_edges = mesh->totedge - num_new_edges;
+ MEdge *medge = mesh->medge;
+
+ /* Remember new_edges is a single linklist, so its items are in reversed order... */
+ MEdge *new_med = &medge[mesh->totedge - 1];
+ for (int i = mesh->totedge - 1; i >= num_edges ; i--, new_med--, new_edges = new_edges->next) {
+ BLI_assert(new_edges->new_index == i);
+ BLI_assert(new_edges->new_index != new_edges->orig_index);
+ CustomData_copy_data(&mesh->edata, &mesh->edata, new_edges->orig_index, i, 1);
+ new_med->v1 = new_edges->v1;
+ new_med->v2 = new_edges->v2;
+ }
+}
+
+/* Split faces based on the edge angle and loop normals.
+ * Matches behavior of face splitting in render engines.
+ *
+ * NOTE: Will leave CD_NORMAL loop data layer which is
+ * used by render engines to set shading up.
+ */
+void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
+{
+ const int num_polys = mesh->totpoly;
+
+ if (num_polys == 0) {
+ return;
+ }
+ BKE_mesh_tessface_clear(mesh);
+
+ MLoopNorSpaceArray *lnors_spacearr = NULL;
+ MemArena *memarena;
+ bool need_vnors_recalc = false;
+
+ if (mesh->flag & ME_AUTOSMOOTH) {
+ lnors_spacearr = MEM_callocN(sizeof(*lnors_spacearr), __func__);
+ /* Compute loop normals and loop normal spaces (a.k.a. smooth fans of faces around vertices). */
+ BKE_mesh_calc_normals_split_ex(mesh, lnors_spacearr);
+ /* Stealing memarena from loop normals space array. */
+ memarena = lnors_spacearr->mem;
+ }
+ else {
+ /* We still have to split out flat faces... */
+ memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ }
+
+ SplitFaceNewVert *new_verts = NULL;
+ SplitFaceNewEdge *new_edges = NULL;
+
+ /* Detect loop normal spaces (a.k.a. smooth fans) that will need a new vert. */
+ const int num_new_verts = split_faces_prepare_new_verts(mesh, lnors_spacearr, &new_verts, memarena, &need_vnors_recalc);
+
+ if (num_new_verts > 0) {
+ /* Reminder: beyond this point, there is no way out, mesh is in invalid state (due to early-reassignment of
+ * loops' vertex and edge indices to new, to-be-created split ones). */
+
+ const int num_new_edges = split_faces_prepare_new_edges(mesh, &new_edges, memarena);
+ /* We can have to split a vertex without having to add a single new edge... */
+ const bool do_edges = (num_new_edges > 0);
+
+ /* Reallocate all vert and edge related data. */
+ mesh->totvert += num_new_verts;
+ mesh->totedge += num_new_edges;
+ CustomData_realloc(&mesh->vdata, mesh->totvert);
+ if (do_edges) {
+ CustomData_realloc(&mesh->edata, mesh->totedge);
+ }
+ /* Update pointers to a newly allocated memory. */
+ BKE_mesh_update_customdata_pointers(mesh, false);
+
+ /* Perform actual split of vertices and edges. */
+ split_faces_split_new_verts(mesh, new_verts, num_new_verts);
+ if (do_edges) {
+ split_faces_split_new_edges(mesh, new_edges, num_new_edges);
+ }
+ }
+
+ /* Note: after this point mesh is expected to be valid again. */
+
+ /* CD_NORMAL is expected to be temporary only. */
+ if (free_loop_normals) {
+ CustomData_free_layers(&mesh->ldata, CD_NORMAL, mesh->totloop);
+ }
+
+ if (lnors_spacearr) {
+ /* Also frees new_verts/edges temp data, since we used its memarena to allocate them. */
+ BKE_lnor_spacearr_free(lnors_spacearr);
+ MEM_freeN(lnors_spacearr);
+ }
+ else {
+ BLI_memarena_free(memarena);
+ }
+
+ if (need_vnors_recalc) {
+ BKE_mesh_calc_normals(mesh);
+ }
+#ifdef VALIDATE_MESH
+ BKE_mesh_validate(mesh, true, true);
+#endif
+}
+
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
Main *bmain, Scene *sce, Object *ob,
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index f9eba118383..0d0055113b7 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -304,13 +304,13 @@ void BKE_mesh_calc_normals_poly(
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
- TIMEIT_START(BKE_mesh_calc_normals);
+ TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
#endif
BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
NULL, false);
#ifdef DEBUG_TIME
- TIMEIT_END(BKE_mesh_calc_normals);
+ TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
#endif
}
@@ -630,7 +630,6 @@ typedef struct LoopSplitTaskDataCommon {
* Note we do not need to protect it, though, since two different tasks will *always* affect different
* elements in the arrays. */
MLoopNorSpaceArray *lnors_spacearr;
- BLI_bitmap *sharp_verts;
float (*loopnors)[3];
short (*clnors_data)[2];
@@ -643,11 +642,8 @@ typedef struct LoopSplitTaskDataCommon {
const int *loop_to_poly;
const float (*polynors)[3];
+ int numLoops;
int numPolys;
-
- /* ***** Workers communication. ***** */
- ThreadQueue *task_queue;
-
} LoopSplitTaskDataCommon;
#define INDEX_UNSET INT_MIN
@@ -655,6 +651,50 @@ typedef struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
+static void loop_manifold_fan_around_vert_next(
+ const MLoop *mloops, const MPoly *mpolys,
+ const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
+ const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index)
+{
+ const MLoop *mlfan_next;
+ const MPoly *mpfan_next;
+
+ /* Warning! This is rather complex!
+ * We have to find our next edge around the vertex (fan mode).
+ * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
+ * whether both loops using current edge are in the same direction or not, and whether
+ * mlfan_curr_index actually uses the vertex we are fanning around!
+ * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
+ * (i.e. not the future mlfan_curr)...
+ */
+ *r_mlfan_curr_index = (e2lfan_curr[0] == *r_mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
+ *r_mpfan_curr_index = loop_to_poly[*r_mlfan_curr_index];
+
+ BLI_assert(*r_mlfan_curr_index >= 0);
+ BLI_assert(*r_mpfan_curr_index >= 0);
+
+ mlfan_next = &mloops[*r_mlfan_curr_index];
+ mpfan_next = &mpolys[*r_mpfan_curr_index];
+ if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) ||
+ ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index))
+ {
+ /* We need the previous loop, but current one is our vertex's loop. */
+ *r_mlfan_vert_index = *r_mlfan_curr_index;
+ if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) {
+ *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
+ }
+ }
+ else {
+ /* We need the next loop, which is also our vertex's loop. */
+ if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) {
+ *r_mlfan_curr_index = mpfan_next->loopstart;
+ }
+ *r_mlfan_vert_index = *r_mlfan_curr_index;
+ }
+ *r_mlfan_curr = &mloops[*r_mlfan_curr_index];
+ /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+}
+
static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
@@ -680,7 +720,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
*/
copy_v3_v3(*lnor, polynors[mp_index]);
- /* printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index); */
+// printf("BASIC: handling loop %d / edge %d / vert %d / poly %d\n", ml_curr_index, ml_curr->e, ml_curr->v, mp_index);
/* If needed, generate this (simple!) lnor space. */
if (lnors_spacearr) {
@@ -747,8 +787,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
const MEdge *me_org = &medges[ml_curr->e]; /* ml_curr would be mlfan_prev if we needed that one */
const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
- const MLoop *mlfan_curr, *mlfan_next;
- const MPoly *mpfan_next;
+ const MLoop *mlfan_curr;
float lnor[3] = {0.0f, 0.0f, 0.0f};
/* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
@@ -787,7 +826,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
}
}
- /* printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e); */
+// printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
while (true) {
const MEdge *me_curr = &medges[mlfan_curr->e];
@@ -803,7 +842,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
normalize_v3(vec_curr);
}
- /* printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index); */
+// printf("\thandling edge %d / loop %d\n", mlfan_curr->e, mlfan_curr_index);
{
/* Code similar to accumulate_vertex_normals_poly. */
@@ -845,46 +884,16 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Current edge is sharp and we have finished with this fan of faces around this vert,
* or this vert is smooth, and we have completed a full turn around it.
*/
- /* printf("FAN: Finished!\n"); */
+// printf("FAN: Finished!\n");
break;
}
copy_v3_v3(vec_prev, vec_curr);
- /* Warning! This is rather complex!
- * We have to find our next edge around the vertex (fan mode).
- * First we find the next loop, which is either previous or next to mlfan_curr_index, depending
- * whether both loops using current edge are in the same direction or not, and whether
- * mlfan_curr_index actually uses the vertex we are fanning around!
- * mlfan_curr_index is the index of mlfan_next here, and mlfan_next is not the real next one
- * (i.e. not the future mlfan_curr)...
- */
- mlfan_curr_index = (e2lfan_curr[0] == mlfan_curr_index) ? e2lfan_curr[1] : e2lfan_curr[0];
- mpfan_curr_index = loop_to_poly[mlfan_curr_index];
-
- BLI_assert(mlfan_curr_index >= 0);
- BLI_assert(mpfan_curr_index >= 0);
-
- mlfan_next = &mloops[mlfan_curr_index];
- mpfan_next = &mpolys[mpfan_curr_index];
- if ((mlfan_curr->v == mlfan_next->v && mlfan_curr->v == mv_pivot_index) ||
- (mlfan_curr->v != mlfan_next->v && mlfan_curr->v != mv_pivot_index))
- {
- /* We need the previous loop, but current one is our vertex's loop. */
- mlfan_vert_index = mlfan_curr_index;
- if (--mlfan_curr_index < mpfan_next->loopstart) {
- mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
- }
- }
- else {
- /* We need the next loop, which is also our vertex's loop. */
- if (++mlfan_curr_index >= mpfan_next->loopstart + mpfan_next->totloop) {
- mlfan_curr_index = mpfan_next->loopstart;
- }
- mlfan_vert_index = mlfan_curr_index;
- }
- mlfan_curr = &mloops[mlfan_curr_index];
- /* And now we are back in sync, mlfan_curr_index is the index of mlfan_curr! Pff! */
+ /* Find next loop of the smooth fan. */
+ loop_manifold_fan_around_vert_next(
+ mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
+ &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
e2lfan_curr = edge_to_loops[mlfan_curr->e];
}
@@ -955,31 +964,25 @@ static void loop_split_worker_do(
}
}
-static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+static void loop_split_worker(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid))
{
- LoopSplitTaskDataCommon *common_data = taskdata;
- LoopSplitTaskData *data_buff;
+ LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool);
+ LoopSplitTaskData *data = taskdata;
/* Temp edge vectors stack, only used when computing lnor spacearr. */
BLI_Stack *edge_vectors = common_data->lnors_spacearr ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
#ifdef DEBUG_TIME
- TIMEIT_START(loop_split_worker);
+ TIMEIT_START_AVERAGED(loop_split_worker);
#endif
- while ((data_buff = BLI_thread_queue_pop(common_data->task_queue))) {
- LoopSplitTaskData *data = data_buff;
- int i;
-
- for (i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
- /* A NULL ml_curr is used to tag ended data! */
- if (data->ml_curr == NULL) {
- break;
- }
- loop_split_worker_do(common_data, data, edge_vectors);
+ for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
+ /* A NULL ml_curr is used to tag ended data! */
+ if (data->ml_curr == NULL) {
+ break;
}
- MEM_freeN(data_buff);
+ loop_split_worker_do(common_data, data, edge_vectors);
}
if (edge_vectors) {
@@ -987,49 +990,117 @@ static void loop_split_worker(TaskPool * __restrict UNUSED(pool), void *taskdata
}
#ifdef DEBUG_TIME
- TIMEIT_END(loop_split_worker);
+ TIMEIT_END_AVERAGED(loop_split_worker);
#endif
}
-/* Note we use data_buff to detect whether we are in threaded context or not, in later case it is NULL. */
-static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const bool threaded)
+/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
+static bool loop_split_generator_check_cyclic_smooth_fan(
+ const MLoop *mloops, const MPoly *mpolys,
+ const int (*edge_to_loops)[2], const int *loop_to_poly, const int *e2l_prev, BLI_bitmap *skip_loops,
+ const MLoop *ml_curr, const MLoop *ml_prev, const int ml_curr_index, const int ml_prev_index,
+ const int mp_curr_index)
+{
+ const unsigned int mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
+ const int *e2lfan_curr;
+ const MLoop *mlfan_curr;
+ /* mlfan_vert_index: the loop of our current edge might not be the loop of our current vertex! */
+ int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
+
+ e2lfan_curr = e2l_prev;
+ if (IS_EDGE_SHARP(e2lfan_curr)) {
+ /* Sharp loop, so not a cyclic smooth fan... */
+ return false;
+ }
+
+ mlfan_curr = ml_prev;
+ mlfan_curr_index = ml_prev_index;
+ mlfan_vert_index = ml_curr_index;
+ mpfan_curr_index = mp_curr_index;
+
+ BLI_assert(mlfan_curr_index >= 0);
+ BLI_assert(mlfan_vert_index >= 0);
+ BLI_assert(mpfan_curr_index >= 0);
+
+ BLI_assert(!BLI_BITMAP_TEST(skip_loops, mlfan_vert_index));
+ BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
+
+ while(true) {
+ /* Find next loop of the smooth fan. */
+ loop_manifold_fan_around_vert_next(
+ mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
+ &mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
+
+ e2lfan_curr = edge_to_loops[mlfan_curr->e];
+
+ if (IS_EDGE_SHARP(e2lfan_curr)) {
+ /* Sharp loop/edge, so not a cyclic smooth fan... */
+ return false;
+ }
+ /* Smooth loop/edge... */
+ else if (BLI_BITMAP_TEST(skip_loops, mlfan_vert_index)) {
+ if (mlfan_vert_index == ml_curr_index) {
+ /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
+ * use initial ml_curr/ml_prev edge as start for this smooth fan. */
+ return true;
+ }
+ /* ... already checked in some previous looping, we can abort. */
+ return false;
+ }
+ else {
+ /* ... we can skip it in future, and keep checking the smooth fan. */
+ BLI_BITMAP_ENABLE(skip_loops, mlfan_vert_index);
+ }
+ }
+}
+
+static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
- BLI_bitmap *sharp_verts = common_data->sharp_verts;
float (*loopnors)[3] = common_data->loopnors;
const MLoop *mloops = common_data->mloops;
const MPoly *mpolys = common_data->mpolys;
+ const int *loop_to_poly = common_data->loop_to_poly;
const int (*edge_to_loops)[2] = common_data->edge_to_loops;
+ const int numLoops = common_data->numLoops;
const int numPolys = common_data->numPolys;
const MPoly *mp;
int mp_index;
- LoopSplitTaskData *data, *data_buff = NULL, data_mem;
+ const MLoop *ml_curr;
+ const MLoop *ml_prev;
+ int ml_curr_index;
+ int ml_prev_index;
+
+ BLI_bitmap *skip_loops = BLI_BITMAP_NEW(numLoops, __func__);
+
+ LoopSplitTaskData *data_buff = NULL;
int data_idx = 0;
/* Temp edge vectors stack, only used when computing lnor spacearr (and we are not multi-threading). */
- BLI_Stack *edge_vectors = (lnors_spacearr && !data_buff) ? BLI_stack_new(sizeof(float[3]), __func__) : NULL;
+ BLI_Stack *edge_vectors = NULL;
#ifdef DEBUG_TIME
- TIMEIT_START(loop_split_generator);
+ TIMEIT_START_AVERAGED(loop_split_generator);
#endif
- if (!threaded) {
- memset(&data_mem, 0, sizeof(data_mem));
- data = &data_mem;
+ if (!pool) {
+ if (lnors_spacearr) {
+ edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
+ }
}
/* We now know edges that can be smoothed (with their vector, and their two loops), and edges that will be hard!
* Now, time to generate the normals.
*/
for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- const MLoop *ml_curr, *ml_prev;
float (*lnors)[3];
const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
- int ml_curr_index = mp->loopstart;
- int ml_prev_index = ml_last_index;
+ ml_curr_index = mp->loopstart;
+ ml_prev_index = ml_last_index;
ml_curr = &mloops[ml_curr_index];
ml_prev = &mloops[ml_prev_index];
@@ -1039,23 +1110,40 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
const int *e2l_curr = edge_to_loops[ml_curr->e];
const int *e2l_prev = edge_to_loops[ml_prev->e];
- if (!IS_EDGE_SHARP(e2l_curr) && (!lnors_spacearr || BLI_BITMAP_TEST_BOOL(sharp_verts, ml_curr->v))) {
- /* A smooth edge, and we are not generating lnor_spacearr, or the related vertex is sharp.
- * We skip it because it is either:
- * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
- * one of its ends, i.e. one of its two sharp edges), or...
- * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
- * are just fine (or it has already be handled in a previous loop in case of needed lnors spacearr)!
- */
- /* printf("Skipping loop %d / edge %d / vert %d(%d)\n", ml_curr_index, ml_curr->e, ml_curr->v, sharp_verts[ml_curr->v]); */
+// printf("Checking loop %d / edge %u / vert %u (sharp edge: %d, skiploop: %d)...",
+// ml_curr_index, ml_curr->e, ml_curr->v, IS_EDGE_SHARP(e2l_curr), BLI_BITMAP_TEST_BOOL(skip_loops, ml_curr_index));
+
+ /* A smooth edge, we have to check for cyclic smooth fan case.
+ * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
+ * 'entry point', otherwise we can skip it. */
+ /* Note: In theory, we could make loop_split_generator_check_cyclic_smooth_fan() store
+ * mlfan_vert_index'es and edge indexes in two stacks, to avoid having to fan again around the vert during
+ * actual computation of clnor & clnorspace. However, this would complicate the code, add more memory usage,
+ * and despite its logical complexity, loop_manifold_fan_around_vert_next() is quite cheap in term of
+ * CPU cycles, so really think it's not worth it. */
+ if (!IS_EDGE_SHARP(e2l_curr) &&
+ (BLI_BITMAP_TEST(skip_loops, ml_curr_index) ||
+ !loop_split_generator_check_cyclic_smooth_fan(
+ mloops, mpolys, edge_to_loops, loop_to_poly, e2l_prev, skip_loops,
+ ml_curr, ml_prev, ml_curr_index, ml_prev_index, mp_index)))
+ {
+// printf("SKIPPING!\n");
}
else {
- if (threaded) {
+ LoopSplitTaskData *data, data_local;
+
+// printf("PROCESSING!\n");
+
+ if (pool) {
if (data_idx == 0) {
data_buff = MEM_callocN(sizeof(*data_buff) * LOOP_SPLIT_TASK_BLOCK_SIZE, __func__);
}
data = &data_buff[data_idx];
}
+ else {
+ data = &data_local;
+ memset(data, 0, sizeof(*data));
+ }
if (IS_EDGE_SHARP(e2l_curr) && IS_EDGE_SHARP(e2l_prev)) {
data->lnor = lnors;
@@ -1091,22 +1179,18 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
data->mp_index = mp_index;
if (lnors_spacearr) {
data->lnor_space = BKE_lnor_space_create(lnors_spacearr);
- /* Tag related vertex as sharp, to avoid fanning around it again (in case it was a smooth one).
- * This *has* to be done outside of workers tasks! */
- BLI_BITMAP_ENABLE(sharp_verts, ml_curr->v);
}
}
- if (threaded) {
+ if (pool) {
data_idx++;
if (data_idx == LOOP_SPLIT_TASK_BLOCK_SIZE) {
- BLI_thread_queue_push(common_data->task_queue, data_buff);
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW);
data_idx = 0;
}
}
else {
loop_split_worker_do(common_data, data, edge_vectors);
- memset(data, 0, sizeof(data_mem));
}
}
@@ -1115,44 +1199,32 @@ static void loop_split_generator_do(LoopSplitTaskDataCommon *common_data, const
}
}
- if (threaded) {
- /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */
- if (LIKELY(data_idx)) {
- BLI_thread_queue_push(common_data->task_queue, data_buff);
- }
-
- /* This will signal all other worker threads to wake up and finish! */
- BLI_thread_queue_nowait(common_data->task_queue);
+ /* Last block of data... Since it is calloc'ed and we use first NULL item as stopper, everything is fine. */
+ if (pool && data_idx) {
+ BLI_task_pool_push(pool, loop_split_worker, data_buff, true, TASK_PRIORITY_LOW);
}
if (edge_vectors) {
BLI_stack_free(edge_vectors);
}
+ MEM_freeN(skip_loops);
#ifdef DEBUG_TIME
- TIMEIT_END(loop_split_generator);
+ TIMEIT_END_AVERAGED(loop_split_generator);
#endif
}
-static void loop_split_generator(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- LoopSplitTaskDataCommon *common_data = taskdata;
-
- loop_split_generator_do(common_data, true);
-}
-
/**
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry (splitting edges).
*/
void BKE_mesh_normals_loop_split(
- const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
+ const MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
const bool use_split_normals, float split_angle,
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
{
-
/* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
BLI_assert(use_split_normals || !(r_lnors_spacearr));
@@ -1185,8 +1257,6 @@ void BKE_mesh_normals_loop_split(
return;
}
- {
-
/* Mapping edge -> loops.
* If that edge is used by more than two loops (polys), it is always sharp (and tagged as such, see below).
* We also use the second loop index as a kind of flag: smooth edge: > 0,
@@ -1196,33 +1266,25 @@ void BKE_mesh_normals_loop_split(
* store the negated value of loop index instead of INDEX_INVALID to retrieve the real value later in code).
* Note also that lose edges always have both values set to 0!
*/
- int (*edge_to_loops)[2] = MEM_callocN(sizeof(int[2]) * (size_t)numEdges, __func__);
+ int (*edge_to_loops)[2] = MEM_callocN(sizeof(*edge_to_loops) * (size_t)numEdges, __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(int) * (size_t)numLoops, __func__);
+ int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_mallocN(sizeof(*loop_to_poly) * (size_t)numLoops, __func__);
MPoly *mp;
- int mp_index, me_index;
- bool check_angle = (split_angle < (float)M_PI);
- int i;
+ int mp_index;
- BLI_bitmap *sharp_verts = NULL;
- MLoopNorSpaceArray _lnors_spacearr = {NULL};
+ /* When using custom loop normals, disable the angle feature! */
+ const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL);
- LoopSplitTaskDataCommon common_data = {NULL};
+ MLoopNorSpaceArray _lnors_spacearr = {NULL};
#ifdef DEBUG_TIME
- TIMEIT_START(BKE_mesh_normals_loop_split);
+ TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
#endif
if (check_angle) {
- /* When using custom loop normals, disable the angle feature! */
- if (clnors_data) {
- check_angle = false;
- }
- else {
- split_angle = cosf(split_angle);
- }
+ split_angle = cosf(split_angle);
}
if (!r_lnors_spacearr && clnors_data) {
@@ -1231,7 +1293,6 @@ void BKE_mesh_normals_loop_split(
}
if (r_lnors_spacearr) {
BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
- sharp_verts = BLI_BITMAP_NEW((size_t)numVerts, __func__);
}
/* This first loop check which edges are actually smooth, and compute edge vectors. */
@@ -1285,60 +1346,38 @@ void BKE_mesh_normals_loop_split(
}
}
- if (r_lnors_spacearr) {
- /* Tag vertices that have at least one sharp edge as 'sharp' (used for the lnor spacearr computation).
- * XXX This third loop over edges is a bit disappointing, could not find any other way yet.
- * Not really performance-critical anyway.
- */
- for (me_index = 0; me_index < numEdges; me_index++) {
- const int *e2l = edge_to_loops[me_index];
- const MEdge *me = &medges[me_index];
- if (IS_EDGE_SHARP(e2l)) {
- BLI_BITMAP_ENABLE(sharp_verts, me->v1);
- BLI_BITMAP_ENABLE(sharp_verts, me->v2);
- }
- }
- }
-
/* Init data common to all tasks. */
- common_data.lnors_spacearr = r_lnors_spacearr;
- common_data.loopnors = r_loopnors;
- common_data.clnors_data = clnors_data;
-
- common_data.mverts = mverts;
- common_data.medges = medges;
- common_data.mloops = mloops;
- common_data.mpolys = mpolys;
- common_data.sharp_verts = sharp_verts;
- common_data.edge_to_loops = (const int(*)[2])edge_to_loops;
- common_data.loop_to_poly = loop_to_poly;
- common_data.polynors = polynors;
- common_data.numPolys = numPolys;
+ LoopSplitTaskDataCommon common_data = {
+ .lnors_spacearr = r_lnors_spacearr,
+ .loopnors = r_loopnors,
+ .clnors_data = clnors_data,
+ .mverts = mverts,
+ .medges = medges,
+ .mloops = mloops,
+ .mpolys = mpolys,
+ .edge_to_loops = (const int(*)[2])edge_to_loops,
+ .loop_to_poly = loop_to_poly,
+ .polynors = polynors,
+ .numLoops = numLoops,
+ .numPolys = numPolys,
+ };
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead... */
- loop_split_generator_do(&common_data, false);
+ loop_split_generator(NULL, &common_data);
}
else {
TaskScheduler *task_scheduler;
TaskPool *task_pool;
- int nbr_workers;
-
- common_data.task_queue = BLI_thread_queue_init();
task_scheduler = BLI_task_scheduler_get();
- task_pool = BLI_task_pool_create(task_scheduler, NULL);
+ task_pool = BLI_task_pool_create(task_scheduler, &common_data);
+
+ loop_split_generator(task_pool, &common_data);
- nbr_workers = max_ii(2, BLI_task_scheduler_num_threads(task_scheduler));
- for (i = 1; i < nbr_workers; i++) {
- BLI_task_pool_push(task_pool, loop_split_worker, &common_data, false, TASK_PRIORITY_HIGH);
- }
- BLI_task_pool_push(task_pool, loop_split_generator, &common_data, false, TASK_PRIORITY_HIGH);
BLI_task_pool_work_and_wait(task_pool);
BLI_task_pool_free(task_pool);
-
- BLI_thread_queue_free(common_data.task_queue);
}
MEM_freeN(edge_to_loops);
@@ -1347,17 +1386,14 @@ void BKE_mesh_normals_loop_split(
}
if (r_lnors_spacearr) {
- MEM_freeN(sharp_verts);
if (r_lnors_spacearr == &_lnors_spacearr) {
BKE_lnor_spacearr_free(r_lnors_spacearr);
}
}
#ifdef DEBUG_TIME
- TIMEIT_END(BKE_mesh_normals_loop_split);
+ TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split);
#endif
-
- }
}
#undef INDEX_UNSET
diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c
index fd0f49810fb..dbe99acc10b 100644
--- a/source/blender/blenkernel/intern/mesh_render.c
+++ b/source/blender/blenkernel/intern/mesh_render.c
@@ -31,6 +31,10 @@
#include "MEM_guardedalloc.h"
+#include "BLI_utildefines.h"
+#include "BLI_edgehash.h"
+#include "BLI_math_vector.h"
+
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -41,182 +45,680 @@
#include "BKE_mesh.h"
#include "BKE_mesh_render.h"
+#include "bmesh.h"
+
#include "GPU_batch.h"
/* ---------------------------------------------------------------------- */
-/* Mesh Interface */
-
-#define MESH_RENDER_FUNCTION(func_name) \
- if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \
- return mesh_bmesh_##func_name(me); \
- } \
- else { \
- return mesh_struct_##func_name(me); \
- }
-
-
-/* Mesh Implementation */
+/* Mesh/BMesh Interface, direct access to basic data. */
-static int mesh_struct_get_num_edges(Mesh *me)
+static int mesh_render_verts_num_get(Mesh *me)
{
- return me->totedge;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totvert : me->totvert;
}
-static int mesh_struct_get_num_verts(Mesh *me)
+static int mesh_render_edges_num_get(Mesh *me)
{
- return me->totvert;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totedge : me->totedge;
}
-static int mesh_struct_get_num_faces(Mesh *me)
+static int mesh_render_looptri_num_get(Mesh *me)
{
- BKE_mesh_tessface_ensure(me);
- return me->totface;
+ return me->edit_btmesh ? me->edit_btmesh->tottri : poly_to_tri_count(me->totpoly, me->totloop);
}
-static int mesh_struct_get_num_polys(Mesh *me)
+static int mesh_render_polys_num_get(Mesh *me)
{
- return me->totpoly;
+ return me->edit_btmesh ? me->edit_btmesh->bm->totface : me->totpoly;
}
-static MEdge *mesh_struct_get_array_edge(Mesh *me)
+static int UNUSED_FUNCTION(mesh_render_loops_num_get)(Mesh *me)
{
- return CustomData_get_layer(&me->edata, CD_MEDGE);
+ return me->edit_btmesh ? me->edit_btmesh->bm->totloop : me->totloop;
}
-static MFace *mesh_struct_get_array_face(Mesh *me)
+/* ---------------------------------------------------------------------- */
+/* Mesh/BMesh Interface, indirect, partially cached access to complex data. */
+
+typedef struct EdgeAdjacentPolys {
+ int count;
+ int face_index[2];
+} EdgeAdjacentPolys;
+
+typedef struct MeshRenderData {
+ int types;
+
+ int totvert;
+ int totedge;
+ int tottri;
+ int totloop;
+ int totpoly;
+ int totlvert;
+ int totledge;
+
+ BMEditMesh *edit_bmesh;
+ MVert *mvert;
+ MEdge *medge;
+ MLoop *mloop;
+ MPoly *mpoly;
+
+ BMVert *eve_act;
+ BMEdge *eed_act;
+ BMFace *efa_act;
+
+ int crease_ofs;
+ int bweight_ofs;
+
+ /* Data created on-demand (usually not for bmesh-based data). */
+ EdgeHash *ehash;
+ EdgeAdjacentPolys *edges_adjacent_polys;
+ MLoopTri *mlooptri;
+ int *loose_edges;
+ int *loose_verts;
+
+ float (*poly_normals)[3];
+ short (*poly_normals_short)[3];
+ short (*vert_normals_short)[3];
+} MeshRenderData;
+
+enum {
+ MR_DATATYPE_VERT = 1 << 0,
+ MR_DATATYPE_EDGE = 1 << 1,
+ MR_DATATYPE_LOOPTRI = 1 << 2,
+ MR_DATATYPE_LOOP = 1 << 3,
+ MR_DATATYPE_POLY = 1 << 4,
+ MR_DATATYPE_OVERLAY = 1 << 5,
+};
+
+static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
{
- BKE_mesh_tessface_ensure(me);
- return CustomData_get_layer(&me->fdata, CD_MFACE);
+ MeshRenderData *mrdata = MEM_callocN(sizeof(*mrdata), __func__);
+ mrdata->types = types;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *embm = me->edit_btmesh;
+ BMesh *bm = embm->bm;
+
+ mrdata->edit_bmesh = embm;
+
+ int bm_ensure_types = 0;
+ if (types & (MR_DATATYPE_VERT)) {
+ mrdata->totvert = bm->totvert;
+ bm_ensure_types |= BM_VERT;
+ }
+ if (types & (MR_DATATYPE_EDGE)) {
+ mrdata->totedge = bm->totedge;
+ bm_ensure_types |= BM_EDGE;
+ }
+ if (types & MR_DATATYPE_LOOPTRI) {
+ BKE_editmesh_tessface_calc(embm);
+ mrdata->tottri = embm->tottri;
+ }
+ if (types & MR_DATATYPE_LOOP) {
+ mrdata->totloop = bm->totloop;
+ bm_ensure_types |= BM_LOOP;
+ }
+ if (types & MR_DATATYPE_POLY) {
+ mrdata->totpoly = bm->totface;
+ bm_ensure_types |= BM_FACE;
+ }
+ if (types & MR_DATATYPE_OVERLAY) {
+ mrdata->efa_act = BM_mesh_active_face_get(bm, false, true);
+ mrdata->eed_act = BM_mesh_active_edge_get(bm);
+ mrdata->eve_act = BM_mesh_active_vert_get(bm);
+ mrdata->crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE);
+ mrdata->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT);
+ }
+ BM_mesh_elem_index_ensure(bm, bm_ensure_types);
+ BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP);
+ if (types & MR_DATATYPE_OVERLAY) {
+ mrdata->totlvert = mrdata->totledge = 0;
+
+ int *lverts = mrdata->loose_verts = MEM_mallocN(mrdata->totvert * sizeof(int), "Loose Vert");
+ int *ledges = mrdata->loose_edges = MEM_mallocN(mrdata->totedge * sizeof(int), "Loose Edges");
+
+ for (int i = 0; i < mrdata->totvert; ++i) {
+ BMVert *bv = BM_vert_at_index(bm, i);
+
+ /* Loose vert */
+ if (bv->e == NULL) {
+ lverts[mrdata->totlvert] = BM_elem_index_get(bv);
+ mrdata->totlvert++;
+ continue;
+ }
+
+ /* Find Loose Edges */
+ BMEdge *e_iter, *e_first;
+ e_first = e_iter = bv->e;
+ do {
+ if (e_iter->l == NULL) {
+ BMVert *other_vert = BM_edge_other_vert(e_iter, bv);
+
+ /* Verify we do not add the same edge twice */
+ if (BM_elem_index_get(other_vert) > i) {
+ ledges[mrdata->totledge] = BM_elem_index_get(e_iter);
+ mrdata->totledge++;
+ }
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, bv)) != e_first);
+ }
+ mrdata->loose_verts = MEM_reallocN(mrdata->loose_verts, mrdata->totlvert * sizeof(int));
+ mrdata->loose_edges = MEM_reallocN(mrdata->loose_edges, mrdata->totledge * sizeof(int));
+ }
+ }
+ else {
+ if (types & (MR_DATATYPE_VERT)) {
+ mrdata->totvert = me->totvert;
+ mrdata->mvert = CustomData_get_layer(&me->vdata, CD_MVERT);
+ }
+ if (types & (MR_DATATYPE_EDGE)) {
+ mrdata->totedge = me->totedge;
+ mrdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE);
+ }
+ if (types & MR_DATATYPE_LOOPTRI) {
+ const int tottri = mrdata->tottri = poly_to_tri_count(me->totpoly, me->totloop);
+ mrdata->mlooptri = MEM_mallocN(sizeof(*mrdata->mlooptri) * tottri, __func__);
+ BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, mrdata->mlooptri);
+ }
+ if (types & MR_DATATYPE_LOOP) {
+ mrdata->totloop = me->totloop;
+ mrdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
+ }
+ if (types & MR_DATATYPE_POLY) {
+ mrdata->totpoly = me->totpoly;
+ mrdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
+ }
+ }
+
+ return mrdata;
}
-static MLoop *mesh_struct_get_array_loop(Mesh *me)
+static void mesh_render_data_free(MeshRenderData *mrdata)
{
- return me->mloop;
+ if (mrdata->ehash) {
+ BLI_edgehash_free(mrdata->ehash, NULL);
+ }
+ if (mrdata->loose_verts) {
+ MEM_freeN(mrdata->loose_verts);
+ }
+ if (mrdata->loose_edges) {
+ MEM_freeN(mrdata->loose_edges);
+ }
+ if (mrdata->edges_adjacent_polys) {
+ MEM_freeN(mrdata->edges_adjacent_polys);
+ }
+ if (mrdata->mlooptri) {
+ MEM_freeN(mrdata->mlooptri);
+ }
+ if (mrdata->poly_normals) {
+ MEM_freeN(mrdata->poly_normals);
+ }
+ if (mrdata->poly_normals_short) {
+ MEM_freeN(mrdata->poly_normals_short);
+ }
+ if (mrdata->vert_normals_short) {
+ MEM_freeN(mrdata->vert_normals_short);
+ }
+ MEM_freeN(mrdata);
}
-static MPoly *mesh_struct_get_array_poly(Mesh *me)
+static int mesh_render_data_verts_num_get(const MeshRenderData *mrdata)
{
- return me->mpoly;
+ BLI_assert(mrdata->types & MR_DATATYPE_VERT);
+ return mrdata->totvert;
}
-static MVert *mesh_struct_get_array_vert(Mesh *me)
+static int mesh_render_data_loose_verts_num_get(const MeshRenderData *mrdata)
{
- return CustomData_get_layer(&me->vdata, CD_MVERT);
+ BLI_assert(mrdata->types & MR_DATATYPE_OVERLAY);
+ return mrdata->totlvert;
}
-/* BMesh Implementation */
-
-/* NOTE: we may want to get rid of Derived Mesh and
- * access BMesh directly */
-
-static int mesh_bmesh_get_num_verts(Mesh *me)
+static int mesh_render_data_edges_num_get(const MeshRenderData *mrdata)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getNumVerts(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_EDGE);
+ return mrdata->totedge;
}
-static int mesh_bmesh_get_num_edges(Mesh *me)
+static int mesh_render_data_loose_edges_num_get(const MeshRenderData *mrdata)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getNumEdges(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_OVERLAY);
+ return mrdata->totledge;
}
-static int mesh_bmesh_get_num_faces(Mesh *me)
+static int mesh_render_data_looptri_num_get(const MeshRenderData *mrdata)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getNumTessFaces(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_LOOPTRI);
+ return mrdata->tottri;
}
-static int mesh_bmesh_get_num_polys(Mesh *me)
+static int UNUSED_FUNCTION(mesh_render_data_loops_num_get)(const MeshRenderData *mrdata)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getNumPolys(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_LOOP);
+ return mrdata->totloop;
}
-static MEdge *mesh_bmesh_get_array_edge(Mesh *me)
+static int mesh_render_data_polys_num_get(const MeshRenderData *mrdata)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getEdgeArray(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_POLY);
+ return mrdata->totpoly;
}
-static MFace *mesh_bmesh_get_array_face(Mesh *me)
+static float *mesh_render_data_vert_co(const MeshRenderData *mrdata, const int vert_idx)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getTessFaceArray(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_VERT);
+
+ if (mrdata->edit_bmesh) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMVert *bv = BM_vert_at_index(bm, vert_idx);
+ return bv->co;
+ }
+ else {
+ return mrdata->mvert[vert_idx].co;
+ }
}
-static MLoop *mesh_bmesh_get_array_loop(Mesh *me)
+static short *mesh_render_data_vert_nor(const MeshRenderData *mrdata, const int vert_idx)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getLoopArray(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_VERT);
+
+ if (mrdata->edit_bmesh) {
+ static short fno[3];
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMVert *bv = BM_vert_at_index(bm, vert_idx);
+ normal_float_to_short_v3(fno, bv->no);
+ return fno;
+ }
+ else {
+ return mrdata->mvert[vert_idx].no;
+ }
}
-static MPoly *mesh_bmesh_get_array_poly(Mesh *me)
+static void mesh_render_data_edge_verts_indices_get(const MeshRenderData *mrdata, const int edge_idx, int r_vert_idx[2])
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getPolyArray(dm);
+ BLI_assert(mrdata->types & MR_DATATYPE_EDGE);
+
+ if (mrdata->edit_bmesh) {
+ const BMEdge *bm_edge = BM_edge_at_index(mrdata->edit_bmesh->bm, edge_idx);
+ r_vert_idx[0] = BM_elem_index_get(bm_edge->v1);
+ r_vert_idx[1] = BM_elem_index_get(bm_edge->v2);
+ }
+ else {
+ const MEdge *me = &mrdata->medge[edge_idx];
+ r_vert_idx[0] = me->v1;
+ r_vert_idx[1] = me->v2;
+ }
}
-static MVert *mesh_bmesh_get_array_vert(Mesh *me)
+static void mesh_render_data_pnors_pcenter_select_get(MeshRenderData *mrdata, const int poly, float pnors[3], float center[3], bool *selected)
{
- BMEditMesh *bm = me->edit_btmesh;
- DerivedMesh *dm = bm->derivedFinal;
- return dm->getVertArray(dm);
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (mrdata->edit_bmesh) {
+ const BMFace *bf = BM_face_at_index(mrdata->edit_bmesh->bm, poly);
+ BM_face_calc_center_mean(bf, center);
+ BM_face_calc_normal(bf, pnors);
+ *selected = (BM_elem_flag_test(bf, BM_ELEM_SELECT) != 0) ? true : false;
+ }
+ else {
+ MVert *mvert = mrdata->mvert;
+ const MPoly *mpoly = mrdata->mpoly + poly;
+ const MLoop *mloop = mrdata->mloop + mpoly->loopstart;
+
+ BKE_mesh_calc_poly_center(mpoly, mloop, mvert, center);
+ BKE_mesh_calc_poly_normal(mpoly, mloop, mvert, pnors);
+
+ *selected = false; /* No selection if not in edit mode */
+ }
}
-/* Mesh API */
+static bool mesh_render_data_edge_exists(MeshRenderData *mrdata, const int v1, const int v2)
+{
+ BLI_assert(mrdata->types & MR_DATATYPE_EDGE);
+
+ if (mrdata->edit_bmesh) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMVert *bv1 = BM_vert_at_index(bm, v1);
+ BMVert *bv2 = BM_vert_at_index(bm, v2);
+ return BM_edge_exists(bv1, bv2) != NULL;
+ }
+ else {
+ EdgeHash *ehash = mrdata->ehash;
+
+ if (!ehash) {
+ /* Create edge hash on demand. */
+ ehash = mrdata->ehash = BLI_edgehash_new(__func__);
-static int mesh_render_get_num_edges(Mesh *me)
+ MEdge *medge = mrdata->medge;
+ for (int i = 0; i < mrdata->totedge; i++, medge++) {
+ BLI_edgehash_insert(ehash, medge->v1, medge->v2, medge);
+ }
+ }
+
+ return BLI_edgehash_lookup(ehash, v1, v2) != NULL;
+ }
+}
+
+static bool mesh_render_data_edge_vcos_manifold_pnors(
+ MeshRenderData *mrdata, const int edge_index,
+ float **r_vco1, float **r_vco2, float **r_pnor1, float **r_pnor2)
{
- MESH_RENDER_FUNCTION(get_num_edges);
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (mrdata->edit_bmesh) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMEdge *bm_edge = BM_edge_at_index(bm, edge_index);
+ *r_vco1 = bm_edge->v1->co;
+ *r_vco2 = bm_edge->v2->co;
+ if (BM_edge_is_manifold(bm_edge)) {
+ *r_pnor1 = bm_edge->l->f->no;
+ *r_pnor2 = bm_edge->l->radial_next->f->no;
+ return true;
+ }
+ }
+ else {
+ MVert *mvert = mrdata->mvert;
+ MEdge *medge = mrdata->medge;
+ EdgeAdjacentPolys *eap = mrdata->edges_adjacent_polys;
+ float (*pnors)[3] = mrdata->poly_normals;
+
+ if (!eap) {
+ const MLoop *mloop = mrdata->mloop;
+ const MPoly *mpoly = mrdata->mpoly;
+ const int poly_ct = mrdata->totpoly;
+ const bool do_pnors = (pnors == NULL);
+
+ eap = mrdata->edges_adjacent_polys = MEM_callocN(sizeof(*eap) * mrdata->totedge, __func__);
+ if (do_pnors) {
+ pnors = mrdata->poly_normals = MEM_mallocN(sizeof(*pnors) * poly_ct, __func__);
+ }
+
+ for (int i = 0; i < poly_ct; i++, mpoly++) {
+ if (do_pnors) {
+ BKE_mesh_calc_poly_normal(mpoly, mloop + mpoly->loopstart, mvert, pnors[i]);
+ }
+
+ const int loopend = mpoly->loopstart + mpoly->totloop;
+ for (int j = mpoly->loopstart; j < loopend; j++) {
+ const int edge_idx = mloop[j].e;
+ if (eap[edge_idx].count < 2) {
+ eap[edge_idx].face_index[eap[edge_idx].count] = i;
+ }
+ eap[edge_idx].count++;
+ }
+ }
+ }
+ BLI_assert(eap && pnors);
+
+ *r_vco1 = mvert[medge[edge_index].v1].co;
+ *r_vco2 = mvert[medge[edge_index].v2].co;
+ if (eap[edge_index].count == 2) {
+ *r_pnor1 = pnors[eap[edge_index].face_index[0]];
+ *r_pnor2 = pnors[eap[edge_index].face_index[1]];
+ return true;
+ }
+ }
+
+ return false;
}
-static int mesh_render_get_num_faces(Mesh *me)
+static void mesh_render_data_looptri_verts_indices_get(const MeshRenderData *mrdata, const int tri_idx, int r_vert_idx[3])
{
- MESH_RENDER_FUNCTION(get_num_faces);
+ BLI_assert(mrdata->types & (MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP));
+
+ if (mrdata->edit_bmesh) {
+ const BMLoop **bm_looptri = (const BMLoop **)mrdata->edit_bmesh->looptris[tri_idx];
+ r_vert_idx[0] = BM_elem_index_get(bm_looptri[0]->v);
+ r_vert_idx[1] = BM_elem_index_get(bm_looptri[1]->v);
+ r_vert_idx[2] = BM_elem_index_get(bm_looptri[2]->v);
+ }
+ else {
+ const MLoopTri *mlt = &mrdata->mlooptri[tri_idx];
+ r_vert_idx[0] = mrdata->mloop[mlt->tri[0]].v;
+ r_vert_idx[1] = mrdata->mloop[mlt->tri[1]].v;
+ r_vert_idx[2] = mrdata->mloop[mlt->tri[2]].v;
+ }
}
-static int mesh_render_get_num_polys(Mesh *me)
+static bool mesh_render_data_looptri_cos_nors_smooth_get(
+ MeshRenderData *mrdata, const int tri_idx, float *(*r_vert_cos)[3], short **r_tri_nor, short *(*r_vert_nors)[3])
{
- MESH_RENDER_FUNCTION(get_num_polys);
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (mrdata->edit_bmesh) {
+ const BMLoop **bm_looptri = (const BMLoop **)mrdata->edit_bmesh->looptris[tri_idx];
+ short (*pnors_short)[3] = mrdata->poly_normals_short;
+ short (*vnors_short)[3] = mrdata->vert_normals_short;
+
+ if (!pnors_short) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMIter fiter;
+ BMFace *face;
+ int i;
+
+ pnors_short = mrdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * mrdata->totpoly, __func__);
+ BM_ITER_MESH_INDEX(face, &fiter, bm, BM_FACES_OF_MESH, i) {
+ normal_float_to_short_v3(pnors_short[i], face->no);
+ }
+ }
+ if (!vnors_short) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMIter viter;
+ BMVert *vert;
+ int i;
+
+ vnors_short = mrdata->vert_normals_short = MEM_mallocN(sizeof(*vnors_short) * mrdata->totvert, __func__);
+ BM_ITER_MESH_INDEX(vert, &viter, bm, BM_VERT, i) {
+ normal_float_to_short_v3(vnors_short[i], vert->no);
+ }
+ }
+
+ (*r_vert_cos)[0] = bm_looptri[0]->v->co;
+ (*r_vert_cos)[1] = bm_looptri[1]->v->co;
+ (*r_vert_cos)[2] = bm_looptri[2]->v->co;
+ *r_tri_nor = pnors_short[BM_elem_index_get(bm_looptri[0]->f)];
+ (*r_vert_nors)[0] = vnors_short[BM_elem_index_get(bm_looptri[0]->v)];
+ (*r_vert_nors)[1] = vnors_short[BM_elem_index_get(bm_looptri[1]->v)];
+ (*r_vert_nors)[2] = vnors_short[BM_elem_index_get(bm_looptri[2]->v)];
+
+ return BM_elem_flag_test_bool(bm_looptri[0]->f, BM_ELEM_SMOOTH);
+ }
+ else {
+ const MLoopTri *mlt = &mrdata->mlooptri[tri_idx];
+ short (*pnors_short)[3] = mrdata->poly_normals_short;
+
+ if (!pnors_short) {
+ float (*pnors)[3] = mrdata->poly_normals;
+
+ if (!pnors) {
+ pnors = mrdata->poly_normals = MEM_mallocN(sizeof(*pnors) * mrdata->totpoly, __func__);
+ BKE_mesh_calc_normals_poly(
+ mrdata->mvert, NULL, mrdata->totvert,
+ mrdata->mloop, mrdata->mpoly, mrdata->totloop, mrdata->totpoly, pnors, true);
+ }
+
+ pnors_short = mrdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * mrdata->totpoly, __func__);
+ for (int i = 0; i < mrdata->totpoly; i++) {
+ normal_float_to_short_v3(pnors_short[i], pnors[i]);
+ }
+ }
+
+ (*r_vert_cos)[0] = mrdata->mvert[mrdata->mloop[mlt->tri[0]].v].co;
+ (*r_vert_cos)[1] = mrdata->mvert[mrdata->mloop[mlt->tri[1]].v].co;
+ (*r_vert_cos)[2] = mrdata->mvert[mrdata->mloop[mlt->tri[2]].v].co;
+ *r_tri_nor = pnors_short[mlt->poly];
+ (*r_vert_nors)[0] = mrdata->mvert[mrdata->mloop[mlt->tri[0]].v].no;
+ (*r_vert_nors)[1] = mrdata->mvert[mrdata->mloop[mlt->tri[1]].v].no;
+ (*r_vert_nors)[2] = mrdata->mvert[mrdata->mloop[mlt->tri[2]].v].no;
+
+ return (mrdata->mpoly[mlt->poly].flag & ME_SMOOTH) != 0;
+ }
}
-static int mesh_render_get_num_verts(Mesh *me)
+/* First 2 bytes are bit flags
+ * 3rd is for sharp edges
+ * 4rd is for creased edges */
+enum {
+ VFLAG_VERTEX_ACTIVE = 1 << 0,
+ VFLAG_VERTEX_SELECTED = 1 << 1,
+ VFLAG_FACE_ACTIVE = 1 << 2,
+ VFLAG_FACE_SELECTED = 1 << 3,
+};
+
+enum {
+ VFLAG_EDGE_EXISTS = 1 << 0,
+ VFLAG_EDGE_ACTIVE = 1 << 1,
+ VFLAG_EDGE_SELECTED = 1 << 2,
+ VFLAG_EDGE_SEAM = 1 << 3,
+ VFLAG_EDGE_SHARP = 1 << 4,
+ /* Beware to not go over 1 << 7
+ * (see gpu_shader_edit_overlay_geom.glsl) */
+};
+
+static unsigned char mesh_render_data_looptri_flag(MeshRenderData *mrdata, const int f)
{
- MESH_RENDER_FUNCTION(get_num_verts);
+ unsigned char fflag = 0;
+
+ if (mrdata->edit_bmesh) {
+ BMFace *bf = mrdata->edit_bmesh->looptris[f][0]->f;
+
+ if (bf == mrdata->efa_act)
+ fflag |= VFLAG_FACE_ACTIVE;
+
+ if (BM_elem_flag_test(bf, BM_ELEM_SELECT))
+ fflag |= VFLAG_FACE_SELECTED;
+ }
+
+ return fflag;
}
-static MEdge *mesh_render_get_array_edge(Mesh *me)
+static unsigned char *mesh_render_data_edge_flag(
+ MeshRenderData *mrdata, const int v1, const int v2, const int e)
{
- MESH_RENDER_FUNCTION(get_array_edge);
+ static unsigned char eflag[4];
+ memset(eflag, 0, sizeof(char) * 4);
+
+ /* if edge exists */
+ if (mrdata->edit_bmesh) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMEdge *be = NULL;
+
+ if (e != -1) be = BM_edge_at_index(bm, e);
+ else be = BM_edge_exists(BM_vert_at_index(bm, v1),
+ BM_vert_at_index(bm, v2));
+
+ if (be != NULL) {
+
+ eflag[1] |= VFLAG_EDGE_EXISTS;
+
+ if (be == mrdata->eed_act)
+ eflag[1] |= VFLAG_EDGE_ACTIVE;
+
+ if (BM_elem_flag_test(be, BM_ELEM_SELECT))
+ eflag[1] |= VFLAG_EDGE_SELECTED;
+
+ if (BM_elem_flag_test(be, BM_ELEM_SEAM))
+ eflag[1] |= VFLAG_EDGE_SEAM;
+
+ if (!BM_elem_flag_test(be, BM_ELEM_SMOOTH))
+ eflag[1] |= VFLAG_EDGE_SHARP;
+
+ /* Use a byte for value range */
+ if (mrdata->crease_ofs != -1) {
+ float crease = BM_ELEM_CD_GET_FLOAT(be, mrdata->crease_ofs);
+ if (crease > 0) {
+ eflag[2] = (char)(crease * 255.0f);
+ }
+ }
+
+ /* Use a byte for value range */
+ if (mrdata->bweight_ofs != -1) {
+ float bweight = BM_ELEM_CD_GET_FLOAT(be, mrdata->bweight_ofs);
+ if (bweight > 0) {
+ eflag[3] = (char)(bweight * 255.0f);
+ }
+ }
+ }
+ }
+ else if ((e == -1) && mesh_render_data_edge_exists(mrdata, v1, v2)) {
+ eflag[1] |= VFLAG_EDGE_EXISTS;
+ }
+
+ return eflag;
}
-static MFace *mesh_render_get_array_face(Mesh *me)
+static unsigned char mesh_render_data_vertex_flag(MeshRenderData *mrdata, const int v)
{
- MESH_RENDER_FUNCTION(get_array_face);
+
+ unsigned char vflag = 0;
+
+ if (mrdata->edit_bmesh) {
+ BMesh *bm = mrdata->edit_bmesh->bm;
+ BMVert *bv = BM_vert_at_index(bm, v);
+
+ /* Current vertex */
+ if (bv == mrdata->eve_act)
+ vflag |= VFLAG_VERTEX_ACTIVE;
+
+ if (BM_elem_flag_test(bv, BM_ELEM_SELECT))
+ vflag |= VFLAG_VERTEX_SELECTED;
+ }
+
+ return vflag;
}
-static MLoop *mesh_render_get_array_loop(Mesh *me)
+static void add_overlay_tri(
+ MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
+ const int v1, const int v2, const int v3, const int f, const int base_vert_idx)
{
- MESH_RENDER_FUNCTION(get_array_loop);
+ const float *pos = mesh_render_data_vert_co(mrdata, v1);
+ unsigned char *eflag = mesh_render_data_edge_flag(mrdata, v2, v3, -1);
+ unsigned char fflag = mesh_render_data_looptri_flag(mrdata, f);
+ unsigned char vflag = mesh_render_data_vertex_flag(mrdata, v1);
+ eflag[0] = fflag | vflag;
+ setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 0, eflag);
+
+ pos = mesh_render_data_vert_co(mrdata, v2);
+ eflag = mesh_render_data_edge_flag(mrdata, v1, v3, -1);
+ vflag = mesh_render_data_vertex_flag(mrdata, v2);
+ eflag[0] = fflag | vflag;
+ setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 1, eflag);
+
+ pos = mesh_render_data_vert_co(mrdata, v3);
+ eflag = mesh_render_data_edge_flag(mrdata, v1, v2, -1);
+ vflag = mesh_render_data_vertex_flag(mrdata, v3);
+ eflag[0] = fflag | vflag;
+ setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 2, eflag);
}
-static MPoly *mesh_render_get_array_poly(Mesh *me)
+static void add_overlay_loose_edge(
+ MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
+ const int v1, const int v2, const int e, const int base_vert_idx)
{
- MESH_RENDER_FUNCTION(get_array_poly);
+ unsigned char *eflag = mesh_render_data_edge_flag(mrdata, 0, 0, e);
+ const float *pos = mesh_render_data_vert_co(mrdata, v1);
+ eflag[0] = mesh_render_data_vertex_flag(mrdata, v1);
+ setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 0, eflag);
+
+ pos = mesh_render_data_vert_co(mrdata, v2);
+ eflag[0] = mesh_render_data_vertex_flag(mrdata, v2);
+ setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 1, eflag);
}
-static MVert *mesh_render_get_array_vert(Mesh *me)
+static void add_overlay_loose_vert(
+ MeshRenderData *mrdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
+ const int v, const int base_vert_idx)
{
- MESH_RENDER_FUNCTION(get_array_vert);
+ unsigned char vflag[4] = {0, 0, 0, 0};
+ const float *pos = mesh_render_data_vert_co(mrdata, v);
+ vflag[0] = mesh_render_data_vertex_flag(mrdata, v);
+ setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
+ setAttrib(vbo, edgeMod_id, base_vert_idx + 0, vflag);
}
/* ---------------------------------------------------------------------- */
@@ -224,6 +726,7 @@ static MVert *mesh_render_get_array_vert(Mesh *me)
typedef struct MeshBatchCache {
VertexBuffer *pos_in_order;
+ VertexBuffer *nor_in_order;
ElementList *edges_in_order;
ElementList *triangles_in_order;
@@ -231,18 +734,31 @@ typedef struct MeshBatchCache {
Batch *all_edges;
Batch *all_triangles;
+ VertexBuffer *pos_with_normals;
+ Batch *triangles_with_normals;
+ Batch *points_with_normals;
Batch *fancy_edges; /* owns its vertex buffer (not shared) */
- Batch *overlay_edges; /* owns its vertex buffer */
+
+ /* TODO : split in 2 buffers to avoid unnecessary
+ * data transfer when selecting/deselecting
+ * and combine into one batch and use offsets to render
+ * Tri / edges / verts separately */
+ Batch *overlay_triangles;
+ Batch *overlay_loose_verts;
+ Batch *overlay_loose_edges;
+ Batch *overlay_facedots;
/* settings to determine if cache is invalid */
bool is_dirty;
int tot_edges;
- int tot_faces;
+ int tot_tris;
int tot_polys;
int tot_verts;
bool is_editmode;
} MeshBatchCache;
+/* Batch cache management. */
+
static bool mesh_batch_cache_valid(Mesh *me)
{
MeshBatchCache *cache = me->batch_cache;
@@ -262,10 +778,10 @@ static bool mesh_batch_cache_valid(Mesh *me)
if (cache->is_editmode) {
return false;
}
- else if ((cache->tot_edges != mesh_render_get_num_edges(me)) ||
- (cache->tot_faces != mesh_render_get_num_faces(me)) ||
- (cache->tot_polys != mesh_render_get_num_polys(me)) ||
- (cache->tot_verts != mesh_render_get_num_verts(me)))
+ else if ((cache->tot_verts != mesh_render_verts_num_get(me)) ||
+ (cache->tot_edges != mesh_render_edges_num_get(me)) ||
+ (cache->tot_tris != mesh_render_looptri_num_get(me)) ||
+ (cache->tot_polys != mesh_render_polys_num_get(me)))
{
return false;
}
@@ -277,13 +793,21 @@ static bool mesh_batch_cache_valid(Mesh *me)
static void mesh_batch_cache_init(Mesh *me)
{
MeshBatchCache *cache = me->batch_cache;
+
+ if (!cache) {
+ cache = me->batch_cache = MEM_callocN(sizeof(*cache), __func__);
+ }
+ else {
+ memset(cache, 0, sizeof(*cache));
+ }
+
cache->is_editmode = me->edit_btmesh != NULL;
if (cache->is_editmode == false) {
- cache->tot_edges = mesh_render_get_num_edges(me);
- cache->tot_faces = mesh_render_get_num_faces(me);
- cache->tot_polys = mesh_render_get_num_polys(me);
- cache->tot_verts = mesh_render_get_num_verts(me);
+ cache->tot_edges = mesh_render_edges_num_get(me);
+ cache->tot_tris = mesh_render_looptri_num_get(me);
+ cache->tot_polys = mesh_render_polys_num_get(me);
+ cache->tot_verts = mesh_render_verts_num_get(me);
}
cache->is_dirty = false;
@@ -292,57 +816,167 @@ static void mesh_batch_cache_init(Mesh *me)
static MeshBatchCache *mesh_batch_cache_get(Mesh *me)
{
if (!mesh_batch_cache_valid(me)) {
- BKE_mesh_batch_cache_free(me);
- me->batch_cache = MEM_callocN(sizeof(MeshBatchCache), "MeshBatchCache");
+ BKE_mesh_batch_cache_clear(me);
mesh_batch_cache_init(me);
}
return me->batch_cache;
}
-static VertexBuffer *mesh_batch_cache_get_pos_in_order(Mesh *me)
+void BKE_mesh_batch_cache_dirty(struct Mesh *me)
{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
+ MeshBatchCache *cache = me->batch_cache;
+ if (cache) {
+ cache->is_dirty = true;
+ }
+}
+
+void BKE_mesh_batch_selection_dirty(struct Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (cache) {
+ /* TODO Separate Flag vbo */
+ if (cache->overlay_triangles) {
+ Batch_discard_all(cache->overlay_triangles);
+ cache->overlay_triangles = NULL;
+ }
+ if (cache->overlay_loose_verts) {
+ Batch_discard_all(cache->overlay_loose_verts);
+ cache->overlay_loose_verts = NULL;
+ }
+ if (cache->overlay_loose_edges) {
+ Batch_discard_all(cache->overlay_loose_edges);
+ cache->overlay_loose_edges = NULL;
+ }
+ if (cache->overlay_facedots) {
+ Batch_discard_all(cache->overlay_facedots);
+ cache->overlay_facedots = NULL;
+ }
+ }
+}
+
+void BKE_mesh_batch_cache_clear(Mesh *me)
+{
+ MeshBatchCache *cache = me->batch_cache;
+ if (!cache) {
+ return;
+ }
+
+ if (cache->all_verts) Batch_discard(cache->all_verts);
+ if (cache->all_edges) Batch_discard(cache->all_edges);
+ if (cache->all_triangles) Batch_discard(cache->all_triangles);
+
+ if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
+ if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
+ if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
+
+ if (cache->overlay_triangles) Batch_discard_all(cache->overlay_triangles);
+ if (cache->overlay_loose_verts) Batch_discard_all(cache->overlay_loose_verts);
+ if (cache->overlay_loose_edges) Batch_discard_all(cache->overlay_loose_edges);
+ if (cache->overlay_facedots) Batch_discard_all(cache->overlay_facedots);
+
+ if (cache->triangles_with_normals) Batch_discard(cache->triangles_with_normals);
+ if (cache->points_with_normals) Batch_discard(cache->points_with_normals);
+ if (cache->pos_with_normals) VertexBuffer_discard(cache->pos_with_normals);
+
+
+ if (cache->fancy_edges) {
+ Batch_discard_all(cache->fancy_edges);
+ }
+}
+
+void BKE_mesh_batch_cache_free(Mesh *me)
+{
+ BKE_mesh_batch_cache_clear(me);
+ MEM_SAFE_FREE(me->batch_cache);
+}
+
+/* Batch cache usage. */
+
+static VertexBuffer *mesh_batch_cache_get_pos_and_normals(MeshRenderData *mrdata, MeshBatchCache *cache)
+{
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (cache->pos_with_normals == NULL) {
+ unsigned int vidx = 0, nidx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned int pos_id, nor_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_SHORT, 3, NORMALIZE_INT_TO_FLOAT);
+ }
+
+ const int tottri = mesh_render_data_looptri_num_get(mrdata);
+
+ cache->pos_with_normals = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(cache->pos_with_normals, tottri * 3);
+
+ for (int i = 0; i < tottri; i++) {
+ float *tri_vert_cos[3];
+ short *tri_nor, *tri_vert_nors[3];
+
+ const bool is_smooth = mesh_render_data_looptri_cos_nors_smooth_get(mrdata, i, &tri_vert_cos, &tri_nor, &tri_vert_nors);
+
+ if (is_smooth) {
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[0]);
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[1]);
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_vert_nors[2]);
+ }
+ else {
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor);
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor);
+ setAttrib(cache->pos_with_normals, nor_id, nidx++, tri_nor);
+ }
+
+ setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[0]);
+ setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[1]);
+ setAttrib(cache->pos_with_normals, pos_id, vidx++, tri_vert_cos[2]);
+ }
+ }
+ return cache->pos_with_normals;
+}
+static VertexBuffer *mesh_batch_cache_get_pos_and_nor_in_order(MeshRenderData *mrdata, MeshBatchCache *cache)
+{
+ BLI_assert(mrdata->types & MR_DATATYPE_VERT);
if (cache->pos_in_order == NULL) {
static VertexFormat format = { 0 };
- static unsigned pos_id;
+ static unsigned pos_id, nor_id;
if (format.attrib_ct == 0) {
/* initialize vertex format */
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_SHORT, 3, NORMALIZE_INT_TO_FLOAT);
}
- const int vertex_ct = mesh_render_get_num_verts(me);
- const MVert *verts = mesh_render_get_array_vert(me);
+ const int vertex_ct = mesh_render_data_verts_num_get(mrdata);
cache->pos_in_order = VertexBuffer_create_with_format(&format);
VertexBuffer_allocate_data(cache->pos_in_order, vertex_ct);
-#if 0
- const unsigned stride = (verts + 1) - verts; /* or sizeof(MVert) */
- fillAttribStride(cache->pos_in_order, pos_id, stride, &verts[0].co);
-#else
for (int i = 0; i < vertex_ct; ++i) {
- setAttrib(cache->pos_in_order, pos_id, i, &verts[i].co);
+ setAttrib(cache->pos_in_order, pos_id, i, mesh_render_data_vert_co(mrdata, i));
+ setAttrib(cache->pos_in_order, nor_id, i, mesh_render_data_vert_nor(mrdata, i));
}
-#endif
}
return cache->pos_in_order;
}
-static ElementList *mesh_batch_cache_get_edges_in_order(Mesh *me)
+static ElementList *mesh_batch_cache_get_edges_in_order(MeshRenderData *mrdata, MeshBatchCache *cache)
{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
if (cache->edges_in_order == NULL) {
- const int vertex_ct = mesh_render_get_num_verts(me);
- const int edge_ct = mesh_render_get_num_edges(me);
- const MEdge *edges = mesh_render_get_array_edge(me);
+ printf("Caching edges in order...\n");
+ const int vertex_ct = mesh_render_data_verts_num_get(mrdata);
+ const int edge_ct = mesh_render_data_edges_num_get(mrdata);
ElementListBuilder elb;
ElementListBuilder_init(&elb, GL_LINES, edge_ct, vertex_ct);
for (int i = 0; i < edge_ct; ++i) {
- const MEdge *edge = edges + i;
- add_line_vertices(&elb, edge->v1, edge->v2);
+ int vert_idx[2];
+ mesh_render_data_edge_verts_indices_get(mrdata, i, vert_idx);
+ add_line_vertices(&elb, vert_idx[0], vert_idx[1]);
}
cache->edges_in_order = ElementList_build(&elb);
}
@@ -350,91 +984,90 @@ static ElementList *mesh_batch_cache_get_edges_in_order(Mesh *me)
return cache->edges_in_order;
}
-static ElementList *mesh_batch_cache_get_triangles_in_order(Mesh *me)
+static ElementList *mesh_batch_cache_get_triangles_in_order(MeshRenderData *mrdata, MeshBatchCache *cache)
{
- MeshBatchCache *cache = mesh_batch_cache_get(me);
+ BLI_assert(mrdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
if (cache->triangles_in_order == NULL) {
- const int vertex_ct = mesh_render_get_num_verts(me);
- const int tessface_ct = mesh_render_get_num_faces(me);
- MFace *tessfaces = mesh_render_get_array_face(me);
+ const int vertex_ct = mesh_render_data_verts_num_get(mrdata);
+ const int tri_ct = mesh_render_data_looptri_num_get(mrdata);
ElementListBuilder elb;
- ElementListBuilder_init(&elb, GL_TRIANGLES, tessface_ct * 2, vertex_ct); /* up to 2 triangles per tessface */
- for (int i = 0; i < tessface_ct; ++i) {
- const MFace *tess = tessfaces + i;
- add_triangle_vertices(&elb, tess->v1, tess->v2, tess->v3);
+ ElementListBuilder_init(&elb, GL_TRIANGLES, tri_ct, vertex_ct);
+ for (int i = 0; i < tri_ct; ++i) {
+ int tri_vert_idx[3];
+ mesh_render_data_looptri_verts_indices_get(mrdata, i, tri_vert_idx);
- if (tess->v4) {
- add_triangle_vertices(&elb, tess->v1, tess->v3, tess->v4);
- }
+ add_triangle_vertices(&elb, tri_vert_idx[0], tri_vert_idx[1], tri_vert_idx[2]);
}
cache->triangles_in_order = ElementList_build(&elb);
}
- /* NOTE: we are reallocating, it would be interesting to reallocating the memory once we
- * know the exactly triangle count (like in BKE_mesh_batch_cache_get_overlay_edges) */
-
return cache->triangles_in_order;
}
-void BKE_mesh_batch_cache_dirty(struct Mesh *me)
+Batch *BKE_mesh_batch_cache_get_all_edges(Mesh *me)
{
- MeshBatchCache *cache = me->batch_cache;
- if (cache) {
- cache->is_dirty = true;
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->all_edges == NULL) {
+ /* create batch from Mesh */
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE);
+
+ cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache),
+ mesh_batch_cache_get_edges_in_order(mrdata, cache));
+
+ mesh_render_data_free(mrdata);
}
+
+ return cache->all_edges;
}
-void BKE_mesh_batch_cache_free(Mesh *me)
+Batch *BKE_mesh_batch_cache_get_all_triangles(Mesh *me)
{
- MeshBatchCache *cache = me->batch_cache;
- if (!cache) {
- return;
- }
-
- if (cache->all_verts) Batch_discard(cache->all_verts);
- if (cache->all_edges) Batch_discard(cache->all_edges);
- if (cache->all_triangles) Batch_discard(cache->all_triangles);
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
- if (cache->pos_in_order) VertexBuffer_discard(cache->pos_in_order);
- if (cache->edges_in_order) ElementList_discard(cache->edges_in_order);
- if (cache->triangles_in_order) ElementList_discard(cache->triangles_in_order);
+ if (cache->all_triangles == NULL) {
+ /* create batch from DM */
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI);
- if (cache->fancy_edges) {
- Batch_discard_all(cache->fancy_edges);
- }
+ cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache),
+ mesh_batch_cache_get_triangles_in_order(mrdata, cache));
- if (cache->overlay_edges) {
- Batch_discard_all(cache->overlay_edges);
+ mesh_render_data_free(mrdata);
}
- MEM_freeN(cache);
- me->batch_cache = NULL;
+ return cache->all_triangles;
}
-Batch *BKE_mesh_batch_cache_get_all_edges(Mesh *me)
+Batch *BKE_mesh_batch_cache_get_triangles_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- if (cache->all_edges == NULL) {
- /* create batch from Mesh */
- cache->all_edges = Batch_create(GL_LINES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_edges_in_order(me));
+ if (cache->triangles_with_normals == NULL) {
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ cache->triangles_with_normals = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_and_normals(mrdata, cache), NULL);
+
+ mesh_render_data_free(mrdata);
}
- return cache->all_edges;
+ return cache->triangles_with_normals;
}
-Batch *BKE_mesh_batch_cache_get_all_triangles(Mesh *me)
+Batch *BKE_mesh_batch_cache_get_points_with_normals(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- if (cache->all_triangles == NULL) {
- /* create batch from DM */
- cache->all_triangles = Batch_create(GL_TRIANGLES, mesh_batch_cache_get_pos_in_order(me), mesh_batch_cache_get_triangles_in_order(me));
+ if (cache->points_with_normals == NULL) {
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ cache->points_with_normals = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_and_normals(mrdata, cache), NULL);
+
+ mesh_render_data_free(mrdata);
}
- return cache->all_triangles;
+ return cache->points_with_normals;
}
Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me)
@@ -443,8 +1076,11 @@ Batch *BKE_mesh_batch_cache_get_all_verts(Mesh *me)
if (cache->all_verts == NULL) {
/* create batch from DM */
- cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_in_order(me), NULL);
- Batch_set_builtin_program(cache->all_verts, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT);
+
+ cache->all_verts = Batch_create(GL_POINTS, mesh_batch_cache_get_pos_and_nor_in_order(mrdata, cache), NULL);
+
+ mesh_render_data_free(mrdata);
}
return cache->all_verts;
@@ -457,7 +1093,7 @@ Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
if (cache->fancy_edges == NULL) {
/* create batch from DM */
static VertexFormat format = { 0 };
- static unsigned pos_id, n1_id, n2_id;
+ static unsigned int pos_id, n1_id, n2_id;
if (format.attrib_ct == 0) {
/* initialize vertex format */
pos_id = add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
@@ -472,48 +1108,24 @@ Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
- const MVert *verts = mesh_render_get_array_vert(me);
- const MEdge *edges = mesh_render_get_array_edge(me);
- const MPoly *polys = mesh_render_get_array_poly(me);
- const MLoop *loops = mesh_render_get_array_loop(me);
- const int edge_ct = mesh_render_get_num_edges(me);
- const int poly_ct = mesh_render_get_num_polys(me);
-
- /* need normal of each face, and which faces are adjacent to each edge */
- typedef struct {
- int count;
- int face_index[2];
- } AdjacentFaces;
-
- float (*face_normal)[3] = MEM_mallocN(poly_ct * 3 * sizeof(float), "face_normal");
- AdjacentFaces *adj_faces = MEM_callocN(edge_ct * sizeof(AdjacentFaces), "adj_faces");
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
- for (int i = 0; i < poly_ct; ++i) {
- const MPoly *poly = polys + i;
-
- BKE_mesh_calc_poly_normal(poly, loops + poly->loopstart, verts, face_normal[i]);
-
- for (int j = poly->loopstart; j < (poly->loopstart + poly->totloop); ++j) {
- AdjacentFaces *adj = adj_faces + loops[j].e;
- if (adj->count < 2)
- adj->face_index[adj->count] = i;
- adj->count++;
- }
- }
+ const int edge_ct = mesh_render_data_edges_num_get(mrdata);
const int vertex_ct = edge_ct * 2; /* these are GL_LINE verts, not mesh verts */
VertexBuffer_allocate_data(vbo, vertex_ct);
for (int i = 0; i < edge_ct; ++i) {
- const MEdge *edge = edges + i;
- const AdjacentFaces *adj = adj_faces + i;
+ float *vcos1, *vcos2;
+ float *pnor1 = NULL, *pnor2 = NULL;
+ const bool is_manifold = mesh_render_data_edge_vcos_manifold_pnors(mrdata, i, &vcos1, &vcos2, &pnor1, &pnor2);
#if USE_10_10_10
PackedNormal n1value = { .x = 0, .y = 0, .z = +511 };
PackedNormal n2value = { .x = 0, .y = 0, .z = -511 };
- if (adj->count == 2) {
- n1value = convert_i10_v3(face_normal[adj->face_index[0]]);
- n2value = convert_i10_v3(face_normal[adj->face_index[1]]);
+ if (is_manifold) {
+ n1value = convert_i10_v3(pnor1);
+ n2value = convert_i10_v3(pnor2);
}
const PackedNormal *n1 = &n1value;
@@ -522,106 +1134,176 @@ Batch *BKE_mesh_batch_cache_get_fancy_edges(Mesh *me)
const float dummy1[3] = { 0.0f, 0.0f, +1.0f };
const float dummy2[3] = { 0.0f, 0.0f, -1.0f };
- const float *n1 = (adj->count == 2) ? face_normal[adj->face_index[0]] : dummy1;
- const float *n2 = (adj->count == 2) ? face_normal[adj->face_index[1]] : dummy2;
+ const float *n1 = (is_manifold) ? pnor1 : dummy1;
+ const float *n2 = (is_manifold) ? pnor2 : dummy2;
#endif
- setAttrib(vbo, pos_id, 2 * i, &verts[edge->v1].co);
+ setAttrib(vbo, pos_id, 2 * i, vcos1);
setAttrib(vbo, n1_id, 2 * i, n1);
setAttrib(vbo, n2_id, 2 * i, n2);
- setAttrib(vbo, pos_id, 2 * i + 1, &verts[edge->v2].co);
+ setAttrib(vbo, pos_id, 2 * i + 1, vcos2);
setAttrib(vbo, n1_id, 2 * i + 1, n1);
setAttrib(vbo, n2_id, 2 * i + 1, n2);
}
- MEM_freeN(adj_faces);
- MEM_freeN(face_normal);
-
cache->fancy_edges = Batch_create(GL_LINES, vbo, NULL);
+
+ mesh_render_data_free(mrdata);
}
return cache->fancy_edges;
}
-static bool edge_is_real(const MEdge *edges, int edge_ct, int v1, int v2)
+static void mesh_batch_cache_create_overlay_batches(Mesh *me)
{
- /* TODO: same thing, except not ridiculously slow */
+ /* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
+ int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
- for (int e = 0; e < edge_ct; ++e) {
- const MEdge *edge = edges + e;
- if ((edge->v1 == v1 && edge->v2 == v2) || (edge->v1 == v2 && edge->v2 == v1)) {
- return true;
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+ MeshRenderData *mrdata = mesh_render_data_create(me, options);
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, data_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data_id = add_attrib(&format, "data", GL_UNSIGNED_BYTE, 4, KEEP_INT);
+ }
+
+ const int tri_ct = mesh_render_data_looptri_num_get(mrdata);
+ const int ledge_ct = mesh_render_data_loose_edges_num_get(mrdata);
+ const int lvert_ct = mesh_render_data_loose_verts_num_get(mrdata);
+
+ if (cache->overlay_triangles == NULL) {
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, tri_ct * 3);
+
+ int gpu_vert_idx = 0;
+ for (int i = 0; i < tri_ct; ++i) {
+ int tri_vert_idx[3];
+ mesh_render_data_looptri_verts_indices_get(mrdata, i, tri_vert_idx);
+ add_overlay_tri(mrdata, vbo, pos_id, data_id,
+ tri_vert_idx[0], tri_vert_idx[1], tri_vert_idx[2], i, gpu_vert_idx);
+ gpu_vert_idx += 3;
}
+
+ cache->overlay_triangles = Batch_create(GL_TRIANGLES, vbo, NULL);
}
- return false;
+ if (cache->overlay_loose_edges == NULL) {
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, ledge_ct * 2);
+
+ int gpu_vert_idx = 0;
+ for (int i = 0; i < ledge_ct; ++i) {
+ int vert_idx[2];
+ mesh_render_data_edge_verts_indices_get(mrdata, mrdata->loose_edges[i], vert_idx);
+ add_overlay_loose_edge(mrdata, vbo, pos_id, data_id,
+ vert_idx[0], vert_idx[1], mrdata->loose_edges[i], gpu_vert_idx);
+ gpu_vert_idx += 2;
+ }
+ cache->overlay_loose_edges = Batch_create(GL_LINES, vbo, NULL);
+ }
+
+ if (cache->overlay_loose_verts == NULL) {
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, lvert_ct);
+
+ int gpu_vert_idx = 0;
+ for (int i = 0; i < lvert_ct; ++i) {
+ add_overlay_loose_vert(mrdata, vbo, pos_id, data_id,
+ mrdata->loose_verts[i], gpu_vert_idx);
+ gpu_vert_idx += 1;
+ }
+ cache->overlay_loose_verts = Batch_create(GL_POINTS, vbo, NULL);
+ }
+
+ mesh_render_data_free(mrdata);
}
-static void add_overlay_tri(
- VertexBuffer *vbo, unsigned pos_id, unsigned edgeMod_id, const MVert *verts,
- const MEdge *edges, int edge_ct, int v1, int v2, int v3, int base_vert_idx)
+Batch *BKE_mesh_batch_cache_get_overlay_triangles(Mesh *me)
{
- const float edgeMods[2] = { 0.0f, 1.0f };
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
- const float *pos = verts[v1].co;
- setAttrib(vbo, pos_id, base_vert_idx + 0, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 0, edgeMods + (edge_is_real(edges, edge_ct, v2, v3) ? 1 : 0));
+ if (cache->overlay_triangles == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
- pos = verts[v2].co;
- setAttrib(vbo, pos_id, base_vert_idx + 1, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 1, edgeMods + (edge_is_real(edges, edge_ct, v3, v1) ? 1 : 0));
+ return cache->overlay_triangles;
+}
- pos = verts[v3].co;
- setAttrib(vbo, pos_id, base_vert_idx + 2, pos);
- setAttrib(vbo, edgeMod_id, base_vert_idx + 2, edgeMods + (edge_is_real(edges, edge_ct, v1, v2) ? 1 : 0));
+Batch *BKE_mesh_batch_cache_get_overlay_loose_edges(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_loose_edges == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+
+ return cache->overlay_loose_edges;
}
-Batch *BKE_mesh_batch_cache_get_overlay_edges(Mesh *me)
+Batch *BKE_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
- if (cache->overlay_edges == NULL) {
- /* create batch from DM */
- static VertexFormat format = { 0 };
- static unsigned pos_id, edgeMod_id;
+ if (cache->overlay_loose_verts == NULL) {
+ mesh_batch_cache_create_overlay_batches(me);
+ }
+ return cache->overlay_loose_verts;
+}
+
+Batch *BKE_mesh_batch_cache_get_overlay_facedots(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->overlay_facedots == NULL) {
+ MeshRenderData *mrdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY);
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, data_id;
if (format.attrib_ct == 0) {
/* initialize vertex format */
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
- edgeMod_id = add_attrib(&format, "edgeWidthModulator", GL_FLOAT, 1, KEEP_FLOAT);
+#if USE_10_10_10
+ data_id = add_attrib(&format, "norAndFlag", COMP_I10, 4, NORMALIZE_INT_TO_FLOAT);
+#else
+ data_id = add_attrib(&format, "norAndFlag", GL_FLOAT, 4, KEEP_FLOAT);
+#endif
}
+
+ const int poly_ct = mesh_render_data_polys_num_get(mrdata);
+
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, poly_ct);
- const int edge_ct = mesh_render_get_num_edges(me);
- const int tessface_ct = mesh_render_get_num_faces(me);
- const MVert *verts = mesh_render_get_array_vert(me);
- const MEdge *edges = mesh_render_get_array_edge(me);
- const MFace *tessfaces = mesh_render_get_array_face(me);
+ for (int i = 0; i < poly_ct; ++i) {
+ float pcenter[3], pnor[3];
+ int selected = 0;
- VertexBuffer_allocate_data(vbo, tessface_ct * 6); /* up to 2 triangles per tessface */
+ mesh_render_data_pnors_pcenter_select_get(mrdata, i, pnor, pcenter, (bool *)&selected);
- int gpu_vert_idx = 0;
- for (int i = 0; i < tessface_ct; ++i) {
- const MFace *tess = tessfaces + i;
- add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v1, tess->v2, tess->v3, gpu_vert_idx);
- gpu_vert_idx += 3;
- /* tessface can be triangle or quad */
- if (tess->v4) {
- add_overlay_tri(vbo, pos_id, edgeMod_id, verts, edges, edge_ct, tess->v3, tess->v2, tess->v4, gpu_vert_idx);
- gpu_vert_idx += 3;
- }
- }
+#if USE_10_10_10
+ PackedNormal nor = { .x = 0, .y = 0, .z = -511 };
+ nor = convert_i10_v3(pnor);
+ nor.w = selected;
+ setAttrib(vbo, data_id, i, &nor);
+#else
+ float nor[4] = {pnor[0], pnor[1], pnor[2], (float)selected};
+ setAttrib(vbo, data_id, i, nor);
+#endif
- /* in some cases all the faces are quad, so no need to reallocate */
- if (vbo->vertex_ct != gpu_vert_idx) {
- VertexBuffer_resize_data(vbo, gpu_vert_idx);
+ setAttrib(vbo, pos_id, i, pcenter);
}
- cache->overlay_edges = Batch_create(GL_TRIANGLES, vbo, NULL);
+ cache->overlay_facedots = Batch_create(GL_POINTS, vbo, NULL);
+
+ mesh_render_data_free(mrdata);
}
- return cache->overlay_edges;
+ return cache->overlay_facedots;
}
#undef MESH_RENDER_FUNCTION
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index c0540192422..0dbc8f27632 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -119,6 +119,8 @@
#include "BKE_camera.h"
#include "BKE_image.h"
+#include "DRW_engine.h"
+
#ifdef WITH_MOD_FLUID
#include "LBM_fluidsim.h"
#endif
@@ -129,7 +131,7 @@
#include "CCGSubSurf.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
/* Vertex parent modifies original BMesh which is not safe for threading.
* Ideally such a modification should be handled as a separate DAG update
@@ -443,6 +445,8 @@ void BKE_object_free(Object *ob)
}
GPU_lamp_free(ob);
+ DRW_object_engine_data_free(ob);
+
BKE_sculptsession_free(ob);
BLI_freelistN(&ob->pc_ids);
@@ -460,10 +464,8 @@ void BKE_object_free(Object *ob)
BKE_previewimg_free(&ob->preview);
- if (ob->collection_settings) {
- BKE_layer_collection_engine_settings_free(ob->collection_settings);
- MEM_freeN(ob->collection_settings);
- }
+ /* don't free, let the base free it */
+ ob->base_collection_properties = NULL;
}
/* actual check for internal data, not context or flags */
@@ -695,6 +697,14 @@ Object *BKE_object_add(
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
lc = BKE_layer_collection_active(sl);
+
+ if (lc == NULL) {
+ BLI_assert(BLI_listbase_count_ex(&sl->layer_collections, 1) == 0);
+ /* when there is no collection linked to this SceneLayer, create one */
+ SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
+ lc = BKE_collection_link(sl, sc);
+ }
+
BKE_collection_object_add(scene, lc->scene_collection, ob);
base = BKE_scene_layer_base_find(sl, ob);
@@ -796,9 +806,9 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
return current;
}
-bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
+bool BKE_object_lod_is_usable(Object *ob, SceneLayer *sl)
{
- bool active = (scene) ? ob == OBACT : false;
+ bool active = (sl) ? ob == OBACT_NEW : false;
return (ob->mode == OB_MODE_OBJECT || !active);
}
@@ -812,11 +822,11 @@ void BKE_object_lod_update(Object *ob, const float camera_position[3])
}
}
-static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
+static Object *lod_ob_get(Object *ob, SceneLayer *sl, int flag)
{
LodLevel *current = ob->currentlod;
- if (!current || !BKE_object_lod_is_usable(ob, scene))
+ if (!current || !BKE_object_lod_is_usable(ob, sl))
return ob;
while (current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) {
@@ -826,14 +836,14 @@ static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
return current->source;
}
-struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_meshob_get(Object *ob, SceneLayer *sl)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MESH);
+ return lod_ob_get(ob, sl, OB_LOD_USE_MESH);
}
-struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_matob_get(Object *ob, SceneLayer *sl)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MAT);
+ return lod_ob_get(ob, sl, OB_LOD_USE_MAT);
}
#endif /* WITH_GAMEENGINE */
@@ -1171,6 +1181,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
BLI_listbase_clear(&obn->gpulamp);
BLI_listbase_clear(&obn->pc_ids);
+ BLI_listbase_clear(&obn->drawdata);
obn->mpath = NULL;
@@ -2244,66 +2255,6 @@ void BKE_boundbox_minmax(const BoundBox *bb, float obmat[4][4], float r_min[3],
}
}
-/**
- * Returns a BBox which each dimensions are at least epsilon.
- * \note In case a given dimension needs to be enlarged, its final value will be in [epsilon, 3 * epsilon] range.
- *
- * \param bb the input bbox to check.
- * \param bb_temp the temp bbox to modify (\a bb content is never changed).
- * \param epsilon the minimum dimension to ensure.
- * \return either bb (if nothing needed to be changed) or bb_temp.
- */
-BoundBox *BKE_boundbox_ensure_minimum_dimensions(BoundBox *bb, BoundBox *bb_temp, const float epsilon)
-{
- if (fabsf(bb->vec[0][0] - bb->vec[4][0]) < epsilon) {
- /* Flat along X axis... */
- *bb_temp = *bb;
- bb = bb_temp;
- bb->vec[0][0] -= epsilon;
- bb->vec[1][0] -= epsilon;
- bb->vec[2][0] -= epsilon;
- bb->vec[3][0] -= epsilon;
- bb->vec[4][0] += epsilon;
- bb->vec[5][0] += epsilon;
- bb->vec[6][0] += epsilon;
- bb->vec[7][0] += epsilon;
- }
-
- if (fabsf(bb->vec[0][1] - bb->vec[3][1]) < epsilon) {
- /* Flat along Y axis... */
- if (bb != bb_temp) {
- *bb_temp = *bb;
- bb = bb_temp;
- }
- bb->vec[0][1] -= epsilon;
- bb->vec[1][1] -= epsilon;
- bb->vec[4][1] -= epsilon;
- bb->vec[5][1] -= epsilon;
- bb->vec[2][1] += epsilon;
- bb->vec[3][1] += epsilon;
- bb->vec[6][1] += epsilon;
- bb->vec[7][1] += epsilon;
- }
-
- if (fabsf(bb->vec[0][2] - bb->vec[1][2]) < epsilon) {
- /* Flat along Z axis... */
- if (bb != bb_temp) {
- *bb_temp = *bb;
- bb = bb_temp;
- }
- bb->vec[0][2] -= epsilon;
- bb->vec[3][2] -= epsilon;
- bb->vec[4][2] -= epsilon;
- bb->vec[7][2] -= epsilon;
- bb->vec[1][2] += epsilon;
- bb->vec[2][2] += epsilon;
- bb->vec[5][2] += epsilon;
- bb->vec[6][2] += epsilon;
- }
-
- return bb;
-}
-
BoundBox *BKE_object_boundbox_get(Object *ob)
{
BoundBox *bb = NULL;
@@ -2547,14 +2498,14 @@ void BKE_object_foreach_display_point(
}
void BKE_scene_foreach_display_point(
- Scene *scene, View3D *v3d, const short flag,
+ Scene *scene, SceneLayer *sl,
void (*func_cb)(const float[3], void *), void *user_data)
{
- BaseLegacy *base;
+ Base *base;
Object *ob;
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTED) != 0)) {
ob = base->object;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -3349,33 +3300,33 @@ static void obrel_list_add(LinkNode **links, Object *ob)
}
/*
- * Iterates over all objects of the given scene.
+ * Iterates over all objects of the given scene layer.
* Depending on the eObjectSet flag:
* collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects.
* If OB_SET_VISIBLE or OB_SET_SELECTED are collected,
* then also add related objects according to the given includeFilters.
*/
-LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+LinkNode *BKE_object_relational_superset(struct SceneLayer *scene_layer, eObjectSet objectSet, eObRelationTypes includeFilter)
{
LinkNode *links = NULL;
- BaseLegacy *base;
+ Base *base;
/* Remove markers from all objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = scene_layer->object_bases.first; base; base = base->next) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
/* iterate over all selected and visible objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = scene_layer->object_bases.first; base; base = base->next) {
if (objectSet == OB_SET_ALL) {
/* as we get all anyways just add it */
Object *ob = base->object;
obrel_list_add(&links, ob);
}
else {
- if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) ||
- (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base)))
+ if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE_NEW(base)) ||
+ (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE_NEW(base)))
{
Object *ob = base->object;
@@ -3403,9 +3354,9 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
/* child relationship */
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
- BaseLegacy *local_base;
- for (local_base = scene->base.first; local_base; local_base = local_base->next) {
- if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
+ Base *local_base;
+ for (local_base = scene_layer->object_bases.first; local_base; local_base = local_base->next) {
+ if (BASE_EDITABLE_BGMODE_NEW(local_base)) {
Object *child = local_base->object;
if (obrel_list_test(child)) {
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 46e6d09294d..c85a91cad68 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -55,6 +55,7 @@
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
+#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_material.h"
#include "BKE_image.h"
@@ -342,13 +343,15 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(eval_ctx, scene, ob);
+ if (ob->type == OB_MESH) {
+ BKE_mesh_batch_cache_dirty(ob->data);
+ }
+
ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
}
-void BKE_object_eval_shading(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
- if (ob->type == OB_MESH) {
- BKE_mesh_batch_cache_dirty(ob->data);
- }
+ DEBUG_PRINT("%s on %s\n", __func__, object->id.name);
+ BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index f31ba34a984..3e99dbe37ca 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -27,6 +27,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "BKE_outliner_treehash.h"
@@ -56,7 +57,7 @@ static TseGroup *tse_group_create(void)
return tse_group;
}
-static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
+static void tse_group_add_element(TseGroup *tse_group, TreeStoreElem *elem)
{
if (UNLIKELY(tse_group->size == tse_group->allocated)) {
tse_group->allocated *= 2;
@@ -66,6 +67,26 @@ static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
tse_group->size++;
}
+static void tse_group_remove_element(TseGroup *tse_group, TreeStoreElem *elem)
+{
+ int min_allocated = MAX2(1, tse_group->allocated / 2);
+ BLI_assert(tse_group->allocated == 1 || (tse_group->allocated % 2) == 0);
+
+ tse_group->size--;
+ BLI_assert(tse_group->size >= 0);
+ for (int i = 0; i < tse_group->size; i++) {
+ if (tse_group->elems[i] == elem) {
+ memcpy(tse_group->elems[i], tse_group->elems[i + 1], (tse_group->size - (i + 1)) * sizeof(TreeStoreElem *));
+ break;
+ }
+ }
+
+ if (UNLIKELY(tse_group->size > 0 && tse_group->size <= min_allocated)) {
+ tse_group->allocated = min_allocated;
+ tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
+ }
+}
+
static void tse_group_free(TseGroup *tse_group)
{
MEM_freeN(tse_group->elems);
@@ -140,7 +161,21 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem)
*val_p = tse_group_create();
}
group = *val_p;
- tse_group_add(group, elem);
+ tse_group_add_element(group, elem);
+}
+
+void BKE_outliner_treehash_remove_element(void *treehash, TreeStoreElem *elem)
+{
+ TseGroup *group = BLI_ghash_lookup(treehash, elem);
+
+ BLI_assert(group != NULL);
+ if (group->size <= 1) {
+ /* one element -> remove group completely */
+ BLI_ghash_remove(treehash, elem, NULL, free_treehash_group);
+ }
+ else {
+ tse_group_remove_element(group, elem);
+ }
}
static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 6b954f060d3..ff29c1c3895 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -73,9 +73,9 @@ const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255};
static OverlayControlFlags overlay_flags = 0;
-void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex)
+void BKE_paint_invalidate_overlay_tex(Scene *scene, SceneLayer *sl, const Tex *tex)
{
- Paint *p = BKE_paint_get_active(scene);
+ Paint *p = BKE_paint_get_active(scene, sl);
Brush *br = p->brush;
if (!br)
@@ -87,9 +87,9 @@ void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex)
overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY;
}
-void BKE_paint_invalidate_cursor_overlay(Scene *scene, CurveMapping *curve)
+void BKE_paint_invalidate_cursor_overlay(Scene *scene, SceneLayer *sl, CurveMapping *curve)
{
- Paint *p = BKE_paint_get_active(scene);
+ Paint *p = BKE_paint_get_active(scene, sl);
Brush *br = p->brush;
if (br && br->curve == curve)
@@ -155,13 +155,13 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, PaintMode mode)
return NULL;
}
-Paint *BKE_paint_get_active(Scene *sce)
+Paint *BKE_paint_get_active(Scene *sce, SceneLayer *sl)
{
- if (sce) {
+ if (sce && sl) {
ToolSettings *ts = sce->toolsettings;
- if (sce->basact && sce->basact->object) {
- switch (sce->basact->object->mode) {
+ if (sl->basact && sl->basact->object) {
+ switch (sl->basact->object->mode) {
case OB_MODE_SCULPT:
return &ts->sculpt->paint;
case OB_MODE_VERTEX_PAINT:
@@ -187,14 +187,15 @@ Paint *BKE_paint_get_active(Scene *sce)
Paint *BKE_paint_get_active_from_context(const bContext *C)
{
Scene *sce = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
SpaceImage *sima;
- if (sce) {
+ if (sce && sl) {
ToolSettings *ts = sce->toolsettings;
Object *obact = NULL;
- if (sce->basact && sce->basact->object)
- obact = sce->basact->object;
+ if (sl->basact && sl->basact->object)
+ obact = sl->basact->object;
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
@@ -237,14 +238,15 @@ Paint *BKE_paint_get_active_from_context(const bContext *C)
PaintMode BKE_paintmode_get_active_from_context(const bContext *C)
{
Scene *sce = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
SpaceImage *sima;
- if (sce) {
+ if (sce && sl) {
ToolSettings *ts = sce->toolsettings;
Object *obact = NULL;
- if (sce->basact && sce->basact->object)
- obact = sce->basact->object;
+ if (sl->basact && sl->basact->object)
+ obact = sl->basact->object;
if ((sima = CTX_wm_space_image(C)) != NULL) {
if (obact && obact->mode == OB_MODE_EDIT) {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 4fe4d6e75a6..b0f9875eaac 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -40,6 +40,7 @@
#include "BKE_paint.h"
#include "GPU_buffers.h"
+#include "GPU_immediate.h"
#include "bmesh.h"
@@ -1156,15 +1157,16 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
static void pbvh_draw_BB(PBVH *bvh)
{
- GPU_init_draw_pbvh_BB();
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
for (int a = 0; a < bvh->totnode; a++) {
PBVHNode *node = &bvh->nodes[a];
- GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
+ GPU_draw_pbvh_BB(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos);
}
- GPU_end_draw_pbvh_BB();
+ immUnbindProgram();
}
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -1737,24 +1739,6 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
{
PBVHNodeDrawData *data = data_v;
-#if 0
- /* XXX: Just some quick code to show leaf nodes in different colors */
- float col[3];
- float spec[3] = {0.0f, 0.0f, 0.0f};
-
- if (0) { //is_partial) {
- col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
- }
- else {
- srand((long long)node);
- for (int i = 0; i < 3; ++i)
- col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
- }
-
- GPU_basic_shader_colors(col, spec, 0, 1.0f);
- glColor3f(1, 0, 0);
-#endif
-
if (!(node->flag & PBVH_FullyHidden)) {
GPU_draw_pbvh_buffers(node->draw_buffers,
data->setMaterial,
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index c3f2107c5af..30eb8dcb287 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
Main *bmain = baker->main;
Scene *scene = baker->scene;
Scene *sce_iter; /* SETLOOPER macro only */
- BaseLegacy *base;
+ Base *base;
ListBase pidlist;
PTCacheID *pid = &baker->pid;
PointCache *cache = NULL;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index dc81dac134b..f8a91f63727 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -330,6 +330,9 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
new_sl = new_sl->next;
}
+
+ IDPropertyTemplate val = {0};
+ scen->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
}
/* copy color management settings */
@@ -443,6 +446,12 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_previewimg_id_copy(&scen->id, &sce->id);
+ if (type != SCE_COPY_NEW) {
+ if (sce->collection_properties) {
+ IDP_MergeGroup(scen->collection_properties, sce->collection_properties, true);
+ }
+ }
+
return scen;
}
@@ -569,11 +578,11 @@ void BKE_scene_free(Scene *sce)
sce->collection = NULL;
/* Runtime Engine Data */
- for (RenderEngineSettings *res = sce->engines_settings.first; res; res = res->next) {
- if (res->data)
- MEM_freeN(res->data);
+ if (sce->collection_properties) {
+ IDP_FreeProperty(sce->collection_properties);
+ MEM_freeN(sce->collection_properties);
+ sce->collection_properties = NULL;
}
- BLI_freelistN(&sce->engines_settings);
}
void BKE_scene_init(Scene *sce)
@@ -928,6 +937,10 @@ void BKE_scene_init(Scene *sce)
sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+ IDPropertyTemplate val = {0};
+ sce->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(sce->collection_properties);
+
BKE_scene_layer_add(sce, "Render Layer");
}
@@ -1152,6 +1165,19 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
return iter->phase;
}
+Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
+{
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (SceneLayer *layer = scene->render_layers.first; layer; layer = layer->next) {
+ if (BKE_scene_layer_has_collection(layer, scene_collection)) {
+ return scene;
+ }
+ }
+ }
+
+ return NULL;
+}
+
Object *BKE_scene_camera_find(Scene *sc)
{
BaseLegacy *base;
@@ -1688,21 +1714,37 @@ float get_render_aosss_error(const RenderData *r, float error)
return error;
}
-/* helper function for the SETLOOPER macro */
-BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base)
+/**
+ * Helper function for the SETLOOPER macro
+ *
+ * It iterates over the bases of the active layer and then the bases
+ * of the active layer of the background (set) scenes recursively.
+ */
+Base *_setlooper_base_step(Scene **sce_iter, Base *base)
{
if (base && base->next) {
/* common case, step to the next */
return base->next;
}
- else if (base == NULL && (*sce_iter)->base.first) {
+ else if (base == NULL) {
/* first time looping, return the scenes first base */
- return (BaseLegacy *)(*sce_iter)->base.first;
+
+ /* for the first loop we should get the layer from context */
+ SceneLayer *sl = BKE_scene_layer_context_active((*sce_iter));
+
+ if (sl->object_bases.first) {
+ return (Base *)sl->object_bases.first;
+ }
+ /* no base on this scene layer */
+ goto next_set;
}
else {
+next_set:
/* reached the end, get the next base in the set */
while ((*sce_iter = (*sce_iter)->set)) {
- base = (BaseLegacy *)(*sce_iter)->base.first;
+ SceneLayer *sl = BKE_scene_layer_render_active((*sce_iter));
+ base = (Base *)sl->object_bases.first;
+
if (base) {
return base;
}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 6a491ba5ec4..69454744dc6 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -66,6 +66,7 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_sequencer.h"
#include "BKE_movieclip.h"
@@ -514,7 +515,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make
* artifacts which will then not happen in final render.
*/
IMB_colormanagement_transform_byte_threaded(
- (unsigned char*)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
+ (unsigned char *)ibuf->rect, ibuf->x, ibuf->y, ibuf->channels,
from_colorspace, to_colorspace);
}
else {
@@ -523,7 +524,7 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, bool make
*/
imb_addrectfloatImBuf(ibuf);
IMB_colormanagement_transform_from_byte_threaded(
- ibuf->rect_float, (unsigned char*)ibuf->rect,
+ ibuf->rect_float, (unsigned char *)ibuf->rect,
ibuf->x, ibuf->y, ibuf->channels,
from_colorspace, to_colorspace);
/* We don't need byte buffer anymore. */
@@ -3304,7 +3305,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- scene, camera, width, height, IB_rect,
+ scene, BKE_scene_layer_render_active(scene), camera, width, height, IB_rect,
context->scene->r.seq_prev_type,
(context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0,
use_gpencil, use_background, scene->r.alphamode,
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index fe4bcc738c6..8469351c54a 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
{
Object *ob;
- BaseLegacy *base;
+ Base *base;
NlaTrack *track;
NlaStrip *strip;
Speaker *speaker;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index c4665c40ec4..9a06fa9e848 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -3634,36 +3634,6 @@ static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
}
-/* same as cdDM_drawUVEdges */
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
-{
- MPoly *mpoly = dm->getPolyArray(dm);
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
-
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
static void ccgDM_drawMappedFaces(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMSetMaterial setMaterial,
@@ -4589,7 +4559,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
- ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 36b24fbb2dc..3dfaa1ed77d 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -755,7 +755,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
if (ok) {
r_ref_pos[0] /= weight_sum;
r_ref_pos[1] /= weight_sum;
- } else {
+ }
+ else {
/* No usable tracking data on any track on this frame.
* Use data from neighbouring frames to extrapolate...
*/
@@ -784,7 +785,8 @@ static void average_marker_positions(StabContext *ctx, int framenr, float r_ref_
* Also default to this frame when we're in a gap */
average_marker_positions(ctx, next_lower, r_ref_pos);
- } else if (next_higher < MAXFRAME) {
+ }
+ else if (next_higher < MAXFRAME) {
average_marker_positions(ctx, next_higher, r_ref_pos);
}
use_values_from_fcurves(ctx, false);
@@ -1167,7 +1169,8 @@ static void stabilization_calculate_data(StabContext *ctx,
if (ctx->stab->flag & TRACKING_STABILIZE_SCALE) {
*r_scale = expf(scale_step * scaleinf); /* Averaged in log scale */
- } else {
+ }
+ else {
*r_scale = 1.0f;
}
@@ -1180,8 +1183,8 @@ static void stabilization_calculate_data(StabContext *ctx,
*/
get_animated_target_pos(ctx, framenr, target_pos);
sub_v2_v2(r_translation, target_pos);
- *r_angle -= get_animated_target_rot(ctx,framenr);
- target_scale = get_animated_target_scale(ctx,framenr);
+ *r_angle -= get_animated_target_rot(ctx, framenr);
+ target_scale = get_animated_target_scale(ctx, framenr);
if (target_scale != 0.0f) {
*r_scale /= target_scale;
/* target_scale is an expected/intended reference zoom value */
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 9994d479ce7..156b74f5c3d 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -568,7 +568,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
if (context->ffmpeg_crf >= 0) {
ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf);
- } else {
+ }
+ else {
c->bit_rate = context->ffmpeg_video_bitrate * 1000;
c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
@@ -576,8 +577,8 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
}
if (context->ffmpeg_preset) {
- char const * preset_name;
- switch(context->ffmpeg_preset) {
+ char const *preset_name;
+ switch (context->ffmpeg_preset) {
case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break;
case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break;
case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break;
diff --git a/source/blender/blenlib/BLI_iterator.h b/source/blender/blenlib/BLI_iterator.h
index d154b81ac82..26d2728d432 100644
--- a/source/blender/blenlib/BLI_iterator.h
+++ b/source/blender/blenlib/BLI_iterator.h
@@ -36,15 +36,16 @@ typedef struct Iterator {
typedef void (*IteratorCb)(Iterator *iter);
typedef void (*IteratorBeginCb)(Iterator *iter, void *data_in);
-#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _type, _data_out) \
+#define ITER_BEGIN(callback_begin, callback_next, callback_end, _data_in, _type, _instance) \
{ \
+ _type _instance; \
IteratorCb callback_end_func = callback_end; \
Iterator iter_macro; \
- for (callback_begin(&iter_macro, _data_in); \
+ for (callback_begin(&iter_macro, (_data_in)); \
iter_macro.valid; \
callback_next(&iter_macro)) \
{ \
- _data_out = (_type *) iter_macro.current;
+ _instance = (_type ) iter_macro.current;
#define ITER_END \
} \
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index 91d39801645..ba565fca522 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -95,10 +95,6 @@ typedef void (*BVHTree_NearestPointCallback)(void *userdata, int index, const fl
/* callback must update hit in case it finds a nearest successful hit */
typedef void (*BVHTree_RayCastCallback)(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit);
-/* callback must update nearest in case it finds a nearest result */
-typedef void (*BVHTree_NearestToRayCallback)(void *userdata, const float ray_co[3], const float ray_dir[3],
- const float scale[3], int index, BVHTreeNearest *nearest);
-
/* callback to check if 2 nodes overlap (use thread if intersection results need to be stored) */
typedef bool (*BVHTree_OverlapCallback)(void *userdata, int index_a, int index_b, int thread);
@@ -143,18 +139,6 @@ int BLI_bvhtree_find_nearest(
BVHTree *tree, const float co[3], BVHTreeNearest *nearest,
BVHTree_NearestPointCallback callback, void *userdata);
-int BLI_bvhtree_find_nearest_to_ray_angle(
- BVHTree *tree, const float co[3], const float dir[3],
- const bool ray_is_normalized, const float scale[3],
- BVHTreeNearest *nearest,
- BVHTree_NearestToRayCallback callback, void *userdata);
-
-int BLI_bvhtree_find_nearest_to_ray(
- BVHTree *tree, const float co[3], const float dir[3],
- const bool ray_is_normalized, const float scale[3],
- BVHTreeNearest *nearest,
- BVHTree_NearestToRayCallback callback, void *userdata);
-
int BLI_bvhtree_ray_cast_ex(
BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit,
BVHTree_RayCastCallback callback, void *userdata,
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index 96349a7b066..4ec222c073e 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -76,6 +76,7 @@ int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1);
void BLI_listbase_swaplinks(struct ListBase *listbase, void *vlinka, void *vlinkb) ATTR_NONNULL(1, 2);
+void BLI_listbases_swaplinks(struct ListBase *listbasea, struct ListBase *listbaseb, void *vlinka, void *vlinkb) ATTR_NONNULL(2, 3);
void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src) ATTR_NONNULL(1, 2);
void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1, 2);
diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h
index c7abe6192f7..34fc52c12c0 100644
--- a/source/blender/blenlib/BLI_math_color.h
+++ b/source/blender/blenlib/BLI_math_color.h
@@ -141,6 +141,9 @@ MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float
#define rgba_char_args_set_fl(col, r, g, b, a) \
rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
+#define rgba_float_args_set_ch(col, r, g, b, a) \
+ rgba_float_args_set(col, (r) / 255.0f, (g) / 255.0f, (b) / 255.0f, (a) / 255.0f)
+
MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a);
MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a);
MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 4a85e859c16..f1d9c9571f2 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -298,23 +298,6 @@ bool isect_ray_aabb_v3_simple(
const float bb_min[3], const float bb_max[3],
float *tmin, float *tmax);
-struct NearestRayToAABB_Precalc {
- float ray_origin[3];
- float ray_direction[3];
- float ray_inv_dir[3];
- float cdot_axis[3];
- float idiag_sq[3];
- bool sign[3];
-};
-
-void dist_squared_ray_to_aabb_v3_precalc(
- struct NearestRayToAABB_Precalc *data,
- const float ray_origin[3], const float ray_direction[3]);
-float dist_squared_ray_to_aabb_v3(
- const struct NearestRayToAABB_Precalc *data,
- const float bb_min[3], const float bb_max[3],
- bool r_axis_closest[3]);
-
/* other */
bool isect_sweeping_sphere_tri_v3(const float p1[3], const float p2[3], const float radius,
const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float ipoint[3]);
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index baa1f792018..b6a55d34d14 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -39,14 +39,6 @@ extern "C" {
struct ListBase;
-#ifdef WIN32
-#define SEP '\\'
-#define ALTSEP '/'
-#else
-#define SEP '/'
-#define ALTSEP '\\'
-#endif
-
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1);
void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1);
@@ -60,7 +52,13 @@ void BLI_path_append(char *__restrict dst, const size_t maxlen,
const char *__restrict file) ATTR_NONNULL();
void BLI_join_dirfile(char *__restrict string, const size_t maxlen,
const char *__restrict dir, const char *__restrict file) ATTR_NONNULL();
+size_t BLI_path_join(
+ char *__restrict dst, const size_t dst_len,
+ const char *path_first, ...) ATTR_NONNULL(1, 3) ATTR_SENTINEL(0);
const char *BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+bool BLI_path_name_at_index(
+ const char *__restrict path, const int index,
+ int *__restrict r_offset, int *__restrict r_len) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
#if 0
typedef enum bli_rebase_state {
@@ -83,7 +81,6 @@ bool BLI_path_program_extensions_add_win32(char *name, const size_t maxlen);
#endif
bool BLI_path_program_search(char *fullname, const size_t maxlen, const char *name);
-void BLI_getlastdir(const char *dir, char *last, const size_t maxlen);
bool BLI_testextensie(const char *str, const char *ext) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
bool BLI_testextensie_n(const char *str, ...) ATTR_NONNULL(1) ATTR_SENTINEL(0);
bool BLI_testextensie_array(const char *str, const char **ext_array) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
@@ -143,6 +140,18 @@ bool BLI_path_suffix(char *string, size_t maxlen, const char *suffix, const char
# define FILE_MAX 1024
#endif
+#ifdef WIN32
+# define SEP '\\'
+# define ALTSEP '/'
+# define SEP_STR "\\"
+# define ALTSEP_STR "/"
+#else
+# define SEP '/'
+# define ALTSEP '\\'
+# define SEP_STR "/"
+# define ALTSEP_STR "\\"
+#endif
+
/* Parent and current dir helpers. */
#define FILENAME_PARENT ".."
#define FILENAME_CURRENT "."
diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h
index 59bf3644912..041679ef876 100644
--- a/source/blender/blenlib/BLI_rect.h
+++ b/source/blender/blenlib/BLI_rect.h
@@ -47,6 +47,8 @@ bool BLI_rcti_is_empty(const struct rcti *rect);
bool BLI_rctf_is_empty(const struct rctf *rect);
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax);
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax);
+void BLI_rctf_init_pt_radius(struct rctf *rect, const float xy[2], float size);
+void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size);
void BLI_rcti_init_minmax(struct rcti *rect);
void BLI_rctf_init_minmax(struct rctf *rect);
void BLI_rcti_do_minmax_v(struct rcti *rect, const int xy[2]);
diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h
index 967e0be6d0a..c3c587275e1 100644
--- a/source/blender/blenlib/BLI_task.h
+++ b/source/blender/blenlib/BLI_task.h
@@ -81,6 +81,7 @@ typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata, int
TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata);
TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userdata);
+TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, void *userdata);
void BLI_task_pool_free(TaskPool *pool);
void BLI_task_pool_push_ex(
@@ -95,14 +96,6 @@ void BLI_task_pool_push_from_thread(TaskPool *pool, TaskRunFunction run,
void BLI_task_pool_work_and_wait(TaskPool *pool);
/* cancel all tasks, keep worker threads running */
void BLI_task_pool_cancel(TaskPool *pool);
-/* stop all worker threads */
-void BLI_task_pool_stop(TaskPool *pool);
-
-/* get number of threads allowed to be used by this pool */
-int BLI_pool_get_num_threads(TaskPool *pool);
-
-/* set number of threads allowed to be used by this pool */
-void BLI_pool_set_num_threads(TaskPool *pool, int num_threads);
/* for worker threads, test if canceled */
bool BLI_task_pool_canceled(TaskPool *pool);
@@ -113,9 +106,6 @@ void *BLI_task_pool_userdata(TaskPool *pool);
/* optional mutex to use from run function */
ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool);
-/* number of tasks done, for stats, don't use this to make decisions */
-size_t BLI_task_pool_tasks_done(TaskPool *pool);
-
/* Parallel for routines */
typedef void (*TaskParallelRangeFunc)(void *userdata, const int iter);
typedef void (*TaskParallelRangeFuncEx)(void *userdata, void *userdata_chunk, const int iter, const int thread_id);
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index b14007a88cb..19d9711922e 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -159,29 +159,6 @@ typedef struct BVHRayCastData {
BVHTreeRayHit hit;
} BVHRayCastData;
-typedef struct BVHNearestRayData {
- BVHTree *tree;
- BVHTree_NearestToRayCallback callback;
- void *userdata;
-
- struct {
- bool sign[3];
- float origin[3];
- float direction[3];
-
- float direction_scaled_square[3];
- float inv_dir[3];
-
- float cdot_axis[3];
- } ray;
-
- bool pick_smallest[3];
-
- BVHTreeNearest nearest;
-
- float scale[3];
-} BVHNearestRayData;
-
/** \} */
@@ -1900,453 +1877,6 @@ void BLI_bvhtree_ray_cast_all(
/* -------------------------------------------------------------------- */
-/** \name BLI_bvhtree_find_nearest_to_ray functions
- *
- * \{ */
-
-static void dist_squared_ray_to_aabb_scaled_v3_precalc(
- BVHNearestRayData *data,
- const float ray_origin[3], const float ray_direction[3],
- const bool ray_is_normalized, const float scale[3])
-{
- if (scale) {
- copy_v3_v3(data->scale, scale);
- }
- else {
- copy_v3_fl(data->scale, 1.0f);
- }
- /* un-normalize ray */
- if (ray_is_normalized && scale &&
- (data->scale[0] != 1.0f || data->scale[1] != 1.0f || data->scale[2] != 1.0f))
- {
- data->ray.direction[0] = ray_direction[0] * data->scale[0];
- data->ray.direction[1] = ray_direction[1] * data->scale[1];
- data->ray.direction[2] = ray_direction[2] * data->scale[2];
-
- mul_v3_v3fl(data->ray.direction, ray_direction, 1 / len_v3(data->ray.direction));
- }
- else {
- copy_v3_v3(data->ray.direction, ray_direction);
- }
-
- float dir_sq[3];
-
- for (int i = 0; i < 3; i++) {
- data->ray.origin[i] = ray_origin[i];
- data->ray.inv_dir[i] = (data->ray.direction[i] != 0.0f) ?
- (1.0f / data->ray.direction[i]) : FLT_MAX;
- /* It has to be in function of `ray.inv_dir`,
- * since the division of 1 by 0.0f, can be -inf or +inf */
- data->ray.sign[i] = (data->ray.inv_dir[i] < 0.0f);
-
- data->ray.direction_scaled_square[i] = data->ray.direction[i] * data->scale[i];
-
- dir_sq[i] = SQUARE(data->ray.direction_scaled_square[i]);
-
- data->ray.direction_scaled_square[i] *= data->scale[i];
- }
-
- /* `diag_sq` Length square of each face diagonal */
- float diag_sq[3] = {
- dir_sq[1] + dir_sq[2],
- dir_sq[0] + dir_sq[2],
- dir_sq[0] + dir_sq[1],
- };
-
- data->ray.cdot_axis[0] = (diag_sq[0] != 0.0f) ? data->ray.direction[0] / diag_sq[0] : FLT_MAX;
- data->ray.cdot_axis[1] = (diag_sq[1] != 0.0f) ? data->ray.direction[1] / diag_sq[1] : FLT_MAX;
- data->ray.cdot_axis[2] = (diag_sq[2] != 0.0f) ? data->ray.direction[2] / diag_sq[2] : FLT_MAX;
-}
-
-/**
- * Returns the squared distance from a ray to a bound-box `AABB`.
- * It is based on `fast_ray_nearest_hit` solution to obtain
- * the coordinates of the nearest edge of Bound Box to the ray
- */
-MINLINE float dist_squared_ray_to_aabb_scaled_v3__impl(
- const BVHNearestRayData *data,
- const float bv[6], float *r_depth_sq, bool r_axis_closest[3])
-{
-
- /* `tmin` is a vector that has the smaller distances to each of the
- * infinite planes of the `AABB` faces (hit in nearest face X plane,
- * nearest face Y plane and nearest face Z plane) */
- float local_bvmin[3], local_bvmax[3];
-
- if (data->ray.sign[0]) {
- local_bvmin[0] = bv[1];
- local_bvmax[0] = bv[0];
- }
- else {
- local_bvmin[0] = bv[0];
- local_bvmax[0] = bv[1];
- }
-
- if (data->ray.sign[1]) {
- local_bvmin[1] = bv[3];
- local_bvmax[1] = bv[2];
- }
- else {
- local_bvmin[1] = bv[2];
- local_bvmax[1] = bv[3];
- }
-
- if (data->ray.sign[2]) {
- local_bvmin[2] = bv[5];
- local_bvmax[2] = bv[4];
- }
- else {
- local_bvmin[2] = bv[4];
- local_bvmax[2] = bv[5];
- }
-
- sub_v3_v3(local_bvmin, data->ray.origin);
- sub_v3_v3(local_bvmax, data->ray.origin);
-
- const float tmin[3] = {
- local_bvmin[0] * data->ray.inv_dir[0],
- local_bvmin[1] * data->ray.inv_dir[1],
- local_bvmin[2] * data->ray.inv_dir[2],
- };
-
- /* `tmax` is a vector that has the longer distances to each of the
- * infinite planes of the `AABB` faces (hit in farthest face X plane,
- * farthest face Y plane and farthest face Z plane) */
- const float tmax[3] = {
- local_bvmax[0] * data->ray.inv_dir[0],
- local_bvmax[1] * data->ray.inv_dir[1],
- local_bvmax[2] * data->ray.inv_dir[2],
- };
- /* `v1` and `v3` is be the coordinates of the nearest `AABB` edge to the ray*/
- float v1[3], v2[3];
- /* `rtmin` is the highest value of the smaller distances. == max_axis_v3(tmin)
- * `rtmax` is the lowest value of longer distances. == min_axis_v3(tmax)*/
- float rtmin, rtmax, mul;
- /* `main_axis` is the axis equivalent to edge close to the ray */
- int main_axis;
-
- r_axis_closest[0] = false;
- r_axis_closest[1] = false;
- r_axis_closest[2] = false;
-
- /* *** min_axis_v3(tmax) *** */
- if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
- // printf("# Hit in X %s\n", data->sign[0] ? "min", "max");
- rtmax = tmax[0];
- v1[0] = v2[0] = local_bvmax[0];
- mul = local_bvmax[0] * data->ray.direction_scaled_square[0];
- main_axis = 3;
- r_axis_closest[0] = data->ray.sign[0];
- }
- else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
- // printf("# Hit in Y %s\n", data->sign[1] ? "min", "max");
- rtmax = tmax[1];
- v1[1] = v2[1] = local_bvmax[1];
- mul = local_bvmax[1] * data->ray.direction_scaled_square[1];
- main_axis = 2;
- r_axis_closest[1] = data->ray.sign[1];
- }
- else {
- // printf("# Hit in Z %s\n", data->sign[2] ? "min", "max");
- rtmax = tmax[2];
- v1[2] = v2[2] = local_bvmax[2];
- mul = local_bvmax[2] * data->ray.direction_scaled_square[2];
- main_axis = 1;
- r_axis_closest[2] = data->ray.sign[2];
- }
-
- /* *** max_axis_v3(tmin) *** */
- if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
- // printf("# To X %s\n", data->sign[0] ? "max", "min");
- rtmin = tmin[0];
- v1[0] = v2[0] = local_bvmin[0];
- mul += local_bvmin[0] * data->ray.direction_scaled_square[0];
- main_axis -= 3;
- r_axis_closest[0] = !data->ray.sign[0];
- }
- else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
- // printf("# To Y %s\n", data->sign[1] ? "max", "min");
- rtmin = tmin[1];
- v1[1] = v2[1] = local_bvmin[1];
- mul += local_bvmin[1] * data->ray.direction_scaled_square[1];
- main_axis -= 1;
- r_axis_closest[1] = !data->ray.sign[1];
- }
- else {
- // printf("# To Z %s\n", data->sign[2] ? "max", "min");
- rtmin = tmin[2];
- v1[2] = v2[2] = local_bvmin[2];
- mul += local_bvmin[2] * data->ray.direction_scaled_square[2];
- main_axis -= 2;
- r_axis_closest[2] = !data->ray.sign[2];
- }
- /* *** end min/max axis *** */
-
- if (main_axis < 0)
- main_axis += 3;
-
- /* if rtmin < rtmax, ray intersect `AABB` */
- if (rtmin <= rtmax) {
-#ifdef IGNORE_BEHIND_RAY
- /* `if rtmax < depth_min`, the whole `AABB` is behind us */
- if (rtmax < min_depth) {
- return fallback;
- }
-#endif
- const float proj = rtmin * data->ray.direction[main_axis];
-
- if (data->ray.sign[main_axis])
- r_axis_closest[main_axis] = (proj - local_bvmax[main_axis]) < (local_bvmin[main_axis] - proj);
- else
- r_axis_closest[main_axis] = (proj - local_bvmin[main_axis]) < (local_bvmax[main_axis] - proj);
-
- //if (r_depth_sq)
- // *r_depth_sq = SQUARE(rtmin);
-
- return 0.0f;
- }
-#ifdef IGNORE_BEHIND_RAY
- /* `if rtmin < depth_min`, the whole `AABB` is behing us */
- else if (rtmin < min_depth) {
- return fallback;
- }
-#endif
-
- if (data->ray.sign[main_axis]) {
- v1[main_axis] = local_bvmax[main_axis];
- v2[main_axis] = local_bvmin[main_axis];
- }
- else {
- v1[main_axis] = local_bvmin[main_axis];
- v2[main_axis] = local_bvmax[main_axis];
- }
- {
- /* `proj` equals to nearest point on the ray closest to the edge `v1 v2` of the `AABB`. */
- const float proj = mul * data->ray.cdot_axis[main_axis];
- float depth_sq, r_point[3];
- if (v1[main_axis] > proj) { /* the nearest point to the ray is the point v1 */
- r_axis_closest[main_axis] = true;
- /* `depth` is equivalent the distance of the the projection of v1 on the ray */
- depth_sq = mul + data->ray.direction_scaled_square[main_axis] * v1[main_axis];
-
- copy_v3_v3(r_point, v1);
- }
- else if (v2[main_axis] < proj) { /* the nearest point of the ray is the point v2 */
- r_axis_closest[main_axis] = false;
-
- depth_sq = mul + data->ray.direction_scaled_square[main_axis] * v2[main_axis];
-
- copy_v3_v3(r_point, v2);
- }
- else { /* the nearest point of the ray is on the edge of the `AABB`. */
- r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj);
-
- depth_sq = mul + data->ray.direction_scaled_square[main_axis] * proj;
-#if 0
- r_point[0] = main_axis == 0 ? proj : v2[0];
- r_point[1] = main_axis == 1 ? proj : v2[1];
- r_point[2] = main_axis == 2 ? proj : v2[2];
-#else
- v2[main_axis] = proj;
- copy_v3_v3(r_point, v2);
-#endif
- }
- depth_sq *= depth_sq;
-
- if (r_depth_sq)
- *r_depth_sq = depth_sq;
-
- /* TODO: scale can be optional */
- r_point[0] *= data->scale[0];
- r_point[1] *= data->scale[1];
- r_point[2] *= data->scale[2];
-
- return len_squared_v3(r_point) - depth_sq;
- }
-}
-
-/**
- * <pre>
- * + r_point
- * |
- * | dist
- * |
- * +----depth----+orig <-- dir
- *
- * tangent = dist/depth
- * </pre>
- */
-static float calc_tangent_sq(BVHNearestRayData *data, BVHNode *node)
-{
- float depth_sq;
- const float dist_sq = dist_squared_ray_to_aabb_scaled_v3__impl(
- data, node->bv, &depth_sq, data->pick_smallest);
-
- return (dist_sq != 0.0f) ? (dist_sq / depth_sq) : 0.0f;
-}
-
-static float calc_dist_sq_to_ray(BVHNearestRayData *data, BVHNode *node)
-{
- return dist_squared_ray_to_aabb_scaled_v3__impl(
- data, node->bv, NULL,
- data->pick_smallest);
-}
-
-static void dfs_find_lowest_tangent_dfs(BVHNearestRayData *data, BVHNode *node)
-{
- if (node->totnode == 0) {
- if (data->callback) {
- data->callback(data->userdata, data->ray.origin, data->ray.direction,
- data->scale, node->index, &data->nearest);
- }
- else {
- data->nearest.index = node->index;
- data->nearest.dist_sq = calc_tangent_sq(data, node);
- /* TODO: return a value to the data->nearest.co
- * not urgent however since users currently define own callbacks */
- }
- }
- else {
- int i;
- /* First pick the closest node to dive on */
- if (data->pick_smallest[node->main_axis]) {
- for (i = 0; i != node->totnode; i++) {
- if (calc_tangent_sq(data, node->children[i]) < data->nearest.dist_sq) {
- dfs_find_lowest_tangent_dfs(data, node->children[i]);
- }
- }
- }
- else {
- for (i = node->totnode - 1; i >= 0; i--) {
- if (calc_tangent_sq(data, node->children[i]) < data->nearest.dist_sq) {
- dfs_find_lowest_tangent_dfs(data, node->children[i]);
- }
- }
- }
- }
-}
-
-static void dfs_find_nearest_to_ray_dfs(BVHNearestRayData *data, BVHNode *node)
-{
- if (node->totnode == 0) {
- if (data->callback) {
- data->callback(data->userdata, data->ray.origin, data->ray.direction,
- data->scale, node->index, &data->nearest);
- }
- else {
- data->nearest.index = node->index;
- data->nearest.dist_sq = calc_dist_sq_to_ray(data, node);
- /* TODO: return a value to the data->nearest.co
- * not urgent however since users currently define own callbacks */
- }
- }
- else {
- int i;
- /* First pick the closest node to dive on */
- if (data->pick_smallest[node->main_axis]) {
- for (i = 0; i != node->totnode; i++) {
- if (calc_dist_sq_to_ray(data, node->children[i]) < data->nearest.dist_sq) {
- dfs_find_nearest_to_ray_dfs(data, node->children[i]);
- }
- }
- }
- else {
- for (i = node->totnode - 1; i >= 0; i--) {
- if (calc_dist_sq_to_ray(data, node->children[i]) < data->nearest.dist_sq) {
- dfs_find_nearest_to_ray_dfs(data, node->children[i]);
- }
- }
- }
- }
-}
-
-/**
- * Returns the point whose tangent defined by the angle between the point and ray is the lowest
- * nearest.dist_sq returns the angle's tangent
- */
-int BLI_bvhtree_find_nearest_to_ray_angle(
- BVHTree *tree, const float co[3], const float dir[3],
- const bool ray_is_normalized, const float scale[3],
- BVHTreeNearest *nearest,
- BVHTree_NearestToRayCallback callback, void *userdata)
-{
- BVHNearestRayData data;
- BVHNode *root = tree->nodes[tree->totleaf];
-
- data.tree = tree;
-
- data.callback = callback;
- data.userdata = userdata;
-
- dist_squared_ray_to_aabb_scaled_v3_precalc(&data, co, dir, ray_is_normalized, scale);
-
- if (nearest) {
- memcpy(&data.nearest, nearest, sizeof(*nearest));
- }
- else {
- data.nearest.index = -1;
- data.nearest.dist_sq = FLT_MAX;
- }
-
- /* dfs search */
- if (root) {
- if (calc_tangent_sq(&data, root) < data.nearest.dist_sq)
- dfs_find_lowest_tangent_dfs(&data, root);
- }
-
- /* copy back results */
- if (nearest) {
- memcpy(nearest, &data.nearest, sizeof(*nearest));
- }
-
- return data.nearest.index;
-}
-
-/* return the nearest point to ray */
-int BLI_bvhtree_find_nearest_to_ray(
- BVHTree *tree, const float co[3], const float dir[3],
- const bool ray_is_normalized, const float scale[3],
- BVHTreeNearest *nearest,
- BVHTree_NearestToRayCallback callback, void *userdata)
-{
- BVHNearestRayData data;
- BVHNode *root = tree->nodes[tree->totleaf];
-
- data.tree = tree;
-
- data.callback = callback;
- data.userdata = userdata;
-
- dist_squared_ray_to_aabb_scaled_v3_precalc(&data, co, dir, ray_is_normalized, scale);
-
- if (nearest) {
- memcpy(&data.nearest, nearest, sizeof(*nearest));
- }
- else {
- data.nearest.index = -1;
- data.nearest.dist_sq = FLT_MAX;
- }
-
- /* dfs search */
- if (root) {
- if (calc_dist_sq_to_ray(&data, root) < data.nearest.dist_sq) {
- dfs_find_nearest_to_ray_dfs(&data, root);
- }
- }
-
- /* copy back results */
- if (nearest) {
- memcpy(nearest, &data.nearest, sizeof(*nearest));
- }
-
- return data.nearest.index;
-}
-
-/** \} */
-
-
-/* -------------------------------------------------------------------- */
-
/** \name BLI_bvhtree_range_query
*
* Allocs and fills an array with the indexs of node that are on the given spherical range (center, radius).
diff --git a/source/blender/blenlib/intern/array_store.c b/source/blender/blenlib/intern/array_store.c
index 21ddddad32e..295b39c1a2f 100644
--- a/source/blender/blenlib/intern/array_store.c
+++ b/source/blender/blenlib/intern/array_store.c
@@ -217,15 +217,12 @@
/** \name Internal Structs
* \{ */
-typedef unsigned int uint;
-typedef unsigned char ubyte;
-
typedef uint64_t hash_key;
typedef struct BArrayInfo {
size_t chunk_stride;
- uint chunk_count;
+ // uint chunk_count; /* UNUSED (other values are derived from this) */
/* pre-calculated */
size_t chunk_byte_size;
@@ -291,7 +288,7 @@ typedef struct BChunkList {
/* a chunk of an array */
typedef struct BChunk {
- const ubyte *data;
+ const uchar *data;
size_t data_len;
/** number of #BChunkList using this. */
int users;
@@ -332,7 +329,7 @@ static size_t bchunk_list_size(const BChunkList *chunk_list);
* \{ */
static BChunk *bchunk_new(
- BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
+ BArrayMemory *bs_mem, const uchar *data, const size_t data_len)
{
BChunk *chunk = BLI_mempool_alloc(bs_mem->chunk);
chunk->data = data;
@@ -345,9 +342,9 @@ static BChunk *bchunk_new(
}
static BChunk *bchunk_new_copydata(
- BArrayMemory *bs_mem, const ubyte *data, const size_t data_len)
+ BArrayMemory *bs_mem, const uchar *data, const size_t data_len)
{
- ubyte *data_copy = MEM_mallocN(data_len, __func__);
+ uchar *data_copy = MEM_mallocN(data_len, __func__);
memcpy(data_copy, data, data_len);
return bchunk_new(bs_mem, data_copy, data_len);
}
@@ -367,7 +364,7 @@ static void bchunk_decref(
static bool bchunk_data_compare(
const BChunk *chunk,
- const ubyte *data_base, const size_t data_base_len,
+ const uchar *data_base, const size_t data_base_len,
const size_t offset)
{
if (offset + (size_t)chunk->data_len <= data_base_len) {
@@ -426,14 +423,14 @@ static void bchunk_list_decref(
#ifdef USE_VALIDATE_LIST_DATA_PARTIAL
static size_t bchunk_list_data_check(
- const BChunkList *chunk_list, const ubyte *data)
+ const BChunkList *chunk_list, const uchar *data)
{
- size_t total_size = 0;
+ size_t offset = 0;
for (BChunkRef *cref = chunk_list->chunk_refs.first; cref; cref = cref->next) {
- if (memcmp(&data[total_size], cref->link->data, cref->link->data_len) != 0) {
+ if (memcmp(&data[offset], cref->link->data, cref->link->data_len) != 0) {
return false;
}
- total_size += cref->link->data_len;
+ offset += cref->link->data_len;
}
return true;
}
@@ -466,7 +463,7 @@ static void bchunk_list_ensure_min_size_last(
chunk_list->chunk_refs.last = cref->prev;
chunk_list->chunk_refs_len -= 1;
- ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
+ uchar *data_merge = MEM_mallocN(data_merge_len, __func__);
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
memcpy(&data_merge[chunk_prev->data_len], chunk_curr->data, chunk_curr->data_len);
@@ -487,8 +484,8 @@ static void bchunk_list_ensure_min_size_last(
/* merge and split */
const size_t data_prev_len = split;
const size_t data_curr_len = data_merge_len - split;
- ubyte *data_prev = MEM_mallocN(data_prev_len, __func__);
- ubyte *data_curr = MEM_mallocN(data_curr_len, __func__);
+ uchar *data_prev = MEM_mallocN(data_prev_len, __func__);
+ uchar *data_curr = MEM_mallocN(data_curr_len, __func__);
if (data_prev_len <= chunk_prev->data_len) {
const size_t data_curr_shrink_len = chunk_prev->data_len - data_prev_len;
@@ -597,11 +594,10 @@ static void bchunk_list_append_only(
static void bchunk_list_append_data(
const BArrayInfo *info, BArrayMemory *bs_mem,
BChunkList *chunk_list,
- const ubyte *data, const size_t data_len)
+ const uchar *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);
@@ -613,13 +609,13 @@ static void bchunk_list_append_data(
const size_t data_merge_len = chunk_prev->data_len + data_len;
/* realloc for single user */
if (cref->link->users == 1) {
- ubyte *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len);
+ uchar *data_merge = MEM_reallocN((void *)cref->link->data, data_merge_len);
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
cref->link->data = data_merge;
cref->link->data_len = data_merge_len;
}
else {
- ubyte *data_merge = MEM_mallocN(data_merge_len, __func__);
+ uchar *data_merge = MEM_mallocN(data_merge_len, __func__);
memcpy(data_merge, chunk_prev->data, chunk_prev->data_len);
memcpy(&data_merge[chunk_prev->data_len], data, data_len);
cref->link = bchunk_new(bs_mem, data_merge, data_merge_len);
@@ -639,7 +635,7 @@ static void bchunk_list_append_data(
/* don't run this, instead preemptively avoid creating a chunk only to merge it (above). */
#if 0
#ifdef USE_MERGE_CHUNKS
- bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list, chunk_size_min);
+ bchunk_list_ensure_min_size_last(info, bs_mem, chunk_list);
#endif
#endif
}
@@ -654,7 +650,7 @@ static void bchunk_list_append_data(
static void bchunk_list_append_data_n(
const BArrayInfo *info, BArrayMemory *bs_mem,
BChunkList *chunk_list,
- const ubyte *data, size_t data_len)
+ const uchar *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);
@@ -714,7 +710,7 @@ static void bchunk_list_append(
static void bchunk_list_fill_from_array(
const BArrayInfo *info, BArrayMemory *bs_mem,
BChunkList *chunk_list,
- const ubyte *data,
+ const uchar *data,
const size_t data_len)
{
BLI_assert(BLI_listbase_is_empty(&chunk_list->chunk_refs));
@@ -765,13 +761,13 @@ static void bchunk_list_fill_from_array(
#define HASH_INIT (5381)
-BLI_INLINE uint hash_data_single(const ubyte p)
+BLI_INLINE uint hash_data_single(const uchar p)
{
return (HASH_INIT << 5) + HASH_INIT + (unsigned int)p;
}
/* hash bytes, from BLI_ghashutil_strhash_n */
-static uint hash_data(const ubyte *key, size_t n)
+static uint hash_data(const uchar *key, size_t n)
{
const signed char *p;
unsigned int h = HASH_INIT;
@@ -788,7 +784,7 @@ static uint hash_data(const ubyte *key, size_t n)
#ifdef USE_HASH_TABLE_ACCUMULATE
static void hash_array_from_data(
- const BArrayInfo *info, const ubyte *data_slice, const size_t data_slice_len,
+ const BArrayInfo *info, const uchar *data_slice, const size_t data_slice_len,
hash_key *hash_array)
{
if (info->chunk_stride != 1) {
@@ -877,7 +873,7 @@ static void hash_accum_single(hash_key *hash_array, const size_t hash_array_len,
static hash_key key_from_chunk_ref(
const BArrayInfo *info, const BChunkRef *cref,
- /* avoid reallicating each time */
+ /* avoid reallocating each time */
hash_key *hash_store, const size_t hash_store_len)
{
/* in C, will fill in a reusable array */
@@ -899,7 +895,7 @@ static hash_key key_from_chunk_ref(
key = hash_store[0];
/* cache the key */
- if (key == HASH_TABLE_KEY_UNSET) {
+ if (UNLIKELY(key == HASH_TABLE_KEY_UNSET)) {
key = HASH_TABLE_KEY_FALLBACK;
}
chunk->key = key;
@@ -929,12 +925,12 @@ static hash_key key_from_chunk_ref(
static const BChunkRef *table_lookup(
const BArrayInfo *info, BTableRef **table, const size_t table_len, const size_t i_table_start,
- const ubyte *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array)
+ const uchar *data, const size_t data_len, const size_t offset, const hash_key *table_hash_array)
{
size_t size_left = data_len - offset;
hash_key key = table_hash_array[((offset - i_table_start) / info->chunk_stride)];
size_t key_index = (size_t)(key % (hash_key)table_len);
- for (BTableRef *tref = table[key_index]; tref; tref = tref->next) {
+ for (const BTableRef *tref = table[key_index]; tref; tref = tref->next) {
const BChunkRef *cref = tref->cref;
#ifdef USE_HASH_TABLE_KEY_CACHE
if (cref->link->key == key)
@@ -985,7 +981,7 @@ static hash_key key_from_chunk_ref(const BArrayInfo *info, const BChunkRef *cref
static const BChunkRef *table_lookup(
const BArrayInfo *info, BTableRef **table, const size_t table_len, const uint UNUSED(i_table_start),
- const ubyte *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array))
+ const uchar *data, const size_t data_len, const size_t offset, const hash_key *UNUSED(table_hash_array))
{
const size_t data_hash_len = BCHUNK_HASH_LEN * info->chunk_stride; /* TODO, cache */
@@ -1025,7 +1021,7 @@ static const BChunkRef *table_lookup(
*/
static BChunkList *bchunk_list_from_data_merge(
const BArrayInfo *info, BArrayMemory *bs_mem,
- const ubyte *data, const size_t data_len_original,
+ const uchar *data, const size_t data_len_original,
const BChunkList *chunk_list_reference)
{
ASSERT_CHUNKLIST_SIZE(chunk_list_reference, chunk_list_reference->total_size);
@@ -1042,10 +1038,8 @@ static BChunkList *bchunk_list_from_data_merge(
size_t i_prev = 0;
#ifdef USE_FASTPATH_CHUNKS_FIRST
- bool full_match = false;
-
{
- full_match = true;
+ bool full_match = true;
const BChunkRef *cref = chunk_list_reference->chunk_refs.first;
while (i_prev < data_len_original) {
@@ -1433,7 +1427,7 @@ BArrayStore *BLI_array_store_create(
BArrayStore *bs = MEM_callocN(sizeof(BArrayStore), __func__);
bs->info.chunk_stride = stride;
- bs->info.chunk_count = chunk_count;
+ // bs->info.chunk_count = chunk_count;
bs->info.chunk_byte_size = chunk_count * stride;
#ifdef USE_MERGE_CHUNKS
@@ -1579,7 +1573,7 @@ BArrayState *BLI_array_store_state_add(
if (state_reference) {
chunk_list = bchunk_list_from_data_merge(
&bs->info, &bs->memory,
- (const ubyte *)data, data_len,
+ (const uchar *)data, data_len,
/* re-use reference chunks */
state_reference->chunk_list);
}
@@ -1588,7 +1582,7 @@ BArrayState *BLI_array_store_state_add(
bchunk_list_fill_from_array(
&bs->info, &bs->memory,
chunk_list,
- (const ubyte *)data, data_len);
+ (const uchar *)data, data_len);
}
chunk_list->users += 1;
@@ -1655,7 +1649,7 @@ void BLI_array_store_state_data_get(
BLI_assert(data_test_len == state->chunk_list->total_size);
#endif
- ubyte *data_step = (ubyte *)data;
+ uchar *data_step = (uchar *)data;
for (BChunkRef *cref = state->chunk_list->chunk_refs.first; cref; cref = cref->next) {
BLI_assert(cref->link->users > 0);
memcpy(data_step, cref->link->data, cref->link->data_len);
diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c
index c9bf4976ae8..3bf0dfa09fa 100644
--- a/source/blender/blenlib/intern/listbase.c
+++ b/source/blender/blenlib/intern/listbase.c
@@ -170,6 +170,34 @@ void BLI_listbase_swaplinks(ListBase *listbase, void *vlinka, void *vlinkb)
}
/**
+ * Swaps \a vlinka and \a vlinkb from their respective lists. Assumes they are both already in their lista!
+ */
+void BLI_listbases_swaplinks(ListBase *listbasea, ListBase *listbaseb, void *vlinka, void *vlinkb)
+{
+ Link *linka = vlinka;
+ Link *linkb = vlinkb;
+ Link linkc = {NULL};
+
+ if (!linka || !linkb) {
+ return;
+ }
+
+ /* Temporary link to use as placeholder of the links positions */
+ BLI_insertlinkafter(listbasea, linka, &linkc);
+
+ /* Bring linka into linkb position */
+ BLI_remlink(listbasea, linka);
+ BLI_insertlinkafter(listbaseb, linkb, linka);
+
+ /* Bring linkb into linka position */
+ BLI_remlink(listbaseb, linkb);
+ BLI_insertlinkafter(listbasea, &linkc, linkb);
+
+ /* Remove temporary link */
+ BLI_remlink(listbasea, &linkc);
+}
+
+/**
* Removes the head from \a listbase and returns it.
*/
void *BLI_pophead(ListBase *listbase)
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index aeb6a550cd9..58699a0593b 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -2337,224 +2337,6 @@ bool isect_ray_aabb_v3_simple(
}
}
-void dist_squared_ray_to_aabb_v3_precalc(
- struct NearestRayToAABB_Precalc *data,
- const float ray_origin[3], const float ray_direction[3])
-{
- float dir_sq[3];
-
- for (int i = 0; i < 3; i++) {
- data->ray_origin[i] = ray_origin[i];
- data->ray_direction[i] = ray_direction[i];
- data->ray_inv_dir[i] = (data->ray_direction[i] != 0.0f) ? (1.0f / data->ray_direction[i]) : FLT_MAX;
- /* It has to be a function of `ray_inv_dir`,
- * since the division of 1 by 0.0f, can be -inf or +inf */
- data->sign[i] = (data->ray_inv_dir[i] < 0.0f);
-
- dir_sq[i] = SQUARE(data->ray_direction[i]);
- }
-
- /* `diag_sq` Length square of each face diagonal */
- float diag_sq[3] = {
- dir_sq[1] + dir_sq[2],
- dir_sq[0] + dir_sq[2],
- dir_sq[0] + dir_sq[1],
- };
- data->idiag_sq[0] = (diag_sq[0] > FLT_EPSILON) ? (1.0f / diag_sq[0]) : FLT_MAX;
- data->idiag_sq[1] = (diag_sq[1] > FLT_EPSILON) ? (1.0f / diag_sq[1]) : FLT_MAX;
- data->idiag_sq[2] = (diag_sq[2] > FLT_EPSILON) ? (1.0f / diag_sq[2]) : FLT_MAX;
-
- data->cdot_axis[0] = data->ray_direction[0] * data->idiag_sq[0];
- data->cdot_axis[1] = data->ray_direction[1] * data->idiag_sq[1];
- data->cdot_axis[2] = data->ray_direction[2] * data->idiag_sq[2];
-}
-
-/**
- * Returns the squared distance from a ray to a bound-box `AABB`.
- * It is based on `fast_ray_nearest_hit` solution to obtain
- * the coordinates of the nearest edge of Bound Box to the ray
- */
-float dist_squared_ray_to_aabb_v3(
- const struct NearestRayToAABB_Precalc *data,
- const float bb_min[3], const float bb_max[3],
- bool r_axis_closest[3])
-{
- /* `tmin` is a vector that has the smaller distances to each of the
- * infinite planes of the `AABB` faces (hit in nearest face X plane,
- * nearest face Y plane and nearest face Z plane) */
- float local_bvmin[3], local_bvmax[3];
-
- if (data->sign[0] == 0) {
- local_bvmin[0] = bb_min[0] - data->ray_origin[0];
- local_bvmax[0] = bb_max[0] - data->ray_origin[0];
- }
- else {
- local_bvmin[0] = bb_max[0] - data->ray_origin[0];
- local_bvmax[0] = bb_min[0] - data->ray_origin[0];
- }
-
- if (data->sign[1] == 0) {
- local_bvmin[1] = bb_min[1] - data->ray_origin[1];
- local_bvmax[1] = bb_max[1] - data->ray_origin[1];
- }
- else {
- local_bvmin[1] = bb_max[1] - data->ray_origin[1];
- local_bvmax[1] = bb_min[1] - data->ray_origin[1];
- }
-
- if (data->sign[2] == 0) {
- local_bvmin[2] = bb_min[2] - data->ray_origin[2];
- local_bvmax[2] = bb_max[2] - data->ray_origin[2];
- }
- else {
- local_bvmin[2] = bb_max[2] - data->ray_origin[2];
- local_bvmax[2] = bb_min[2] - data->ray_origin[2];
- }
-
- const float tmin[3] = {
- local_bvmin[0] * data->ray_inv_dir[0],
- local_bvmin[1] * data->ray_inv_dir[1],
- local_bvmin[2] * data->ray_inv_dir[2],
- };
-
- /* `tmax` is a vector that has the longer distances to each of the
- * infinite planes of the `AABB` faces (hit in farthest face X plane,
- * farthest face Y plane and farthest face Z plane) */
- const float tmax[3] = {
- local_bvmax[0] * data->ray_inv_dir[0],
- local_bvmax[1] * data->ray_inv_dir[1],
- local_bvmax[2] * data->ray_inv_dir[2],
- };
- /* `v1` and `v3` is be the coordinates of the nearest `AABB` edge to the ray*/
- float v1[3], v2[3];
- /* `rtmin` is the highest value of the smaller distances. == max_axis_v3(tmin)
- * `rtmax` is the lowest value of longer distances. == min_axis_v3(tmax)*/
- float rtmin, rtmax, mul, rdist;
- /* `main_axis` is the axis equivalent to edge close to the ray */
- int main_axis;
-
- r_axis_closest[0] = false;
- r_axis_closest[1] = false;
- r_axis_closest[2] = false;
-
- /* *** min_axis_v3(tmax) *** */
- if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) {
- // printf("# Hit in X %s\n", data->sign[0] ? "min", "max");
- rtmax = tmax[0];
- v1[0] = v2[0] = local_bvmax[0];
- mul = local_bvmax[0] * data->ray_direction[0];
- main_axis = 3;
- r_axis_closest[0] = data->sign[0];
- }
- else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) {
- // printf("# Hit in Y %s\n", data->sign[1] ? "min", "max");
- rtmax = tmax[1];
- v1[1] = v2[1] = local_bvmax[1];
- mul = local_bvmax[1] * data->ray_direction[1];
- main_axis = 2;
- r_axis_closest[1] = data->sign[1];
- }
- else {
- // printf("# Hit in Z %s\n", data->sign[2] ? "min", "max");
- rtmax = tmax[2];
- v1[2] = v2[2] = local_bvmax[2];
- mul = local_bvmax[2] * data->ray_direction[2];
- main_axis = 1;
- r_axis_closest[2] = data->sign[2];
- }
-
- /* *** max_axis_v3(tmin) *** */
- if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) {
- // printf("# To X %s\n", data->sign[0] ? "max", "min");
- rtmin = tmin[0];
- v1[0] = v2[0] = local_bvmin[0];
- mul += local_bvmin[0] * data->ray_direction[0];
- main_axis -= 3;
- r_axis_closest[0] = !data->sign[0];
- }
- else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) {
- // printf("# To Y %s\n", data->sign[1] ? "max", "min");
- rtmin = tmin[1];
- v1[1] = v2[1] = local_bvmin[1];
- mul += local_bvmin[1] * data->ray_direction[1];
- main_axis -= 1;
- r_axis_closest[1] = !data->sign[1];
- }
- else {
- // printf("# To Z %s\n", data->sign[2] ? "max", "min");
- rtmin = tmin[2];
- v1[2] = v2[2] = local_bvmin[2];
- mul += local_bvmin[2] * data->ray_direction[2];
- main_axis -= 2;
- r_axis_closest[2] = !data->sign[2];
- }
- /* *** end min/max axis *** */
-
-
- /* `if rtmax < 0`, the whole `AABB` is behing us */
- if ((rtmax < 0.0f) && (rtmin < 0.0f)) {
- return FLT_MAX;
- }
-
- if (main_axis < 0) {
- main_axis += 3;
- }
-
- if (data->sign[main_axis] == 0) {
- v1[main_axis] = local_bvmin[main_axis];
- v2[main_axis] = local_bvmax[main_axis];
- }
- else {
- v1[main_axis] = local_bvmax[main_axis];
- v2[main_axis] = local_bvmin[main_axis];
- }
-
- /* if rtmin < rtmax, ray intersect `AABB` */
- if (rtmin <= rtmax) {
- const float proj = rtmin * data->ray_direction[main_axis];
- rdist = 0.0f;
- r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj);
- }
- else {
- /* `proj` equals to nearest point on the ray closest to the edge `v1 v2` of the `AABB`. */
- const float proj = mul * data->cdot_axis[main_axis];
- float depth;
- if (v1[main_axis] > proj) { /* the nearest point to the ray is the point v1 */
- /* `depth` is equivalent the distance from the origin to the point v1,
- * Here's a faster way to calculate the dot product of v1 and ray
- * (depth = dot_v3v3(v1, data->ray.direction))*/
- depth = mul + data->ray_direction[main_axis] * v1[main_axis];
- rdist = len_squared_v3(v1) - SQUARE(depth);
- r_axis_closest[main_axis] = true;
- }
- else if (v2[main_axis] < proj) { /* the nearest point of the ray is the point v2 */
- depth = mul + data->ray_direction[main_axis] * v2[main_axis];
- rdist = len_squared_v3(v2) - SQUARE(depth);
- r_axis_closest[main_axis] = false;
- }
- else { /* the nearest point of the ray is on the edge of the `AABB`. */
- float v[2];
- mul *= data->idiag_sq[main_axis];
- if (main_axis == 0) {
- v[0] = (mul * data->ray_direction[1]) - v1[1];
- v[1] = (mul * data->ray_direction[2]) - v1[2];
- }
- else if (main_axis == 1) {
- v[0] = (mul * data->ray_direction[0]) - v1[0];
- v[1] = (mul * data->ray_direction[2]) - v1[2];
- }
- else {
- v[0] = (mul * data->ray_direction[0]) - v1[0];
- v[1] = (mul * data->ray_direction[1]) - v1[1];
- }
- rdist = len_squared_v2(v);
- r_axis_closest[main_axis] = (proj - v1[main_axis]) < (v2[main_axis] - proj);
- }
- }
-
- return rdist;
-}
-
/* find closest point to p on line through (l1, l2) and return lambda,
* where (0 <= lambda <= 1) when cp is in the line segment (l1, l2)
*/
@@ -3069,6 +2851,9 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[
/**
* \note: using #cross_tri_v2 means locations outside the triangle are correctly weighted
+ *
+ * \note This is *exactly* the same calculation as #resolve_tri_uv_v2,
+ * although it has double precision and is used for texture baking, so keep both.
*/
void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
{
@@ -3108,9 +2893,11 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
}
}
-/* same as #barycentric_weights_v2 but works with a quad,
+/**
+ * same as #barycentric_weights_v2 but works with a quad,
* note: untested for values outside the quad's bounds
- * this is #interp_weights_poly_v2 expanded for quads only */
+ * this is #interp_weights_poly_v2 expanded for quads only
+ */
void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2],
const float co[2], float w[4])
{
@@ -3563,6 +3350,8 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3
* Barycentric reverse
*
* Compute coordinates (u, v) for point \a st with respect to triangle (\a st0, \a st1, \a st2)
+ *
+ * \note same basic result as #barycentric_weights_v2, see it's comment for details.
*/
void resolve_tri_uv_v2(float r_uv[2], const float st[2],
const float st0[2], const float st1[2], const float st2[2])
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index 6644e6605a1..7b765cfa939 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1167,30 +1167,6 @@ bool BLI_path_program_search(
}
/**
- * Copies into *last the part of *dir following the second-last slash.
- */
-void BLI_getlastdir(const char *dir, char *last, const size_t maxlen)
-{
- const char *s = dir;
- const char *lslash = NULL;
- const char *prevslash = NULL;
- while (*s) {
- if ((*s == '\\') || (*s == '/')) {
- prevslash = lslash;
- lslash = s;
- }
- s++;
- }
- if (prevslash) {
- BLI_strncpy(last, prevslash + 1, maxlen);
- }
- else {
- BLI_strncpy(last, dir, maxlen);
- }
-}
-
-
-/**
* Sets the specified environment variable to the specified value,
* and clears it if val == NULL.
*/
@@ -1615,6 +1591,90 @@ void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__r
}
/**
+ * Join multiple strings into a path, ensuring only a single path separator between each,
+ * and trailing slash is kept.
+ *
+ * \note If you want a trailing slash, add ``SEP_STR`` as the last path argument,
+ * duplicate slashes will be cleaned up.
+ */
+size_t BLI_path_join(char *__restrict dst, const size_t dst_len, const char *path, ...)
+{
+ if (UNLIKELY(dst_len == 0)) {
+ return 0;
+ }
+ const size_t dst_last = dst_len - 1;
+ size_t ofs = BLI_strncpy_rlen(dst, path, dst_len);
+
+ if (ofs == dst_last) {
+ return ofs;
+ }
+
+ /* remove trailing slashes, unless there are _only_ trailing slashes
+ * (allow "//" as the first argument). */
+ bool has_trailing_slash = false;
+ if (ofs != 0) {
+ size_t len = ofs;
+ while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ len -= 1;
+ }
+ if (len != 0) {
+ ofs = len;
+ }
+ has_trailing_slash = (path[len] != '\0');
+ }
+
+ va_list args;
+ va_start(args, path);
+ while ((path = (const char *) va_arg(args, const char *))) {
+ has_trailing_slash = false;
+ const char *path_init = path;
+ while (ELEM(path[0], SEP, ALTSEP)) {
+ path++;
+ }
+ size_t len = strlen(path);
+ if (len != 0) {
+ while ((len != 0) && ELEM(path[len - 1], SEP, ALTSEP)) {
+ len -= 1;
+ }
+
+ if (len != 0) {
+ /* the very first path may have a slash at the end */
+ if (ofs && !ELEM(dst[ofs - 1], SEP, ALTSEP)) {
+ dst[ofs++] = SEP;
+ if (ofs == dst_last) {
+ break;
+ }
+ }
+ has_trailing_slash = (path[len] != '\0');
+ if (ofs + len >= dst_last) {
+ len = dst_last - ofs;
+ }
+ memcpy(&dst[ofs], path, len);
+ ofs += len;
+ if (ofs == dst_last) {
+ break;
+ }
+ }
+ }
+ else {
+ has_trailing_slash = (path_init != path);
+ }
+ }
+ va_end(args);
+
+ if (has_trailing_slash) {
+ if ((ofs != dst_last) && (ofs != 0) && (ELEM(dst[ofs - 1], SEP, ALTSEP) == 0)) {
+ dst[ofs++] = SEP;
+ }
+ }
+
+ BLI_assert(ofs <= dst_last);
+ dst[ofs] = '\0';
+
+ return ofs;
+}
+
+/**
* like pythons os.path.basename()
*
* \return The pointer into \a path string immediately after last slash,
@@ -1626,6 +1686,71 @@ const char *BLI_path_basename(const char *path)
return filename ? filename + 1 : path;
}
+/**
+ * Get an element of the path at an index, eg:
+ * "/some/path/file.txt" where an index of...
+ * - 0 or -3: "some"
+ * - 1 or -2: "path"
+ * - 2 or -1: "file.txt"
+ *
+ * Ignores multiple slashes at any point in the path (including start/end).
+ */
+bool BLI_path_name_at_index(const char *path, const int index, int *r_offset, int *r_len)
+{
+ if (index >= 0) {
+ int index_step = 0;
+ int prev = -1;
+ int i = 0;
+ while (true) {
+ const char c = path[i];
+ if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (prev + 1 != i) {
+ prev += 1;
+ if (index_step == index) {
+ *r_offset = prev;
+ *r_len = i - prev;
+ /* printf("!!! %d %d\n", start, end); */
+ return true;
+ }
+ index_step += 1;
+ }
+ if (c == '\0') {
+ break;
+ }
+ prev = i;
+ }
+ i += 1;
+ }
+ return false;
+ }
+ else {
+ /* negative number, reverse where -1 is the last element */
+ int index_step = -1;
+ int prev = strlen(path);
+ int i = prev - 1;
+ while (true) {
+ const char c = i >= 0 ? path[i] : '\0';
+ if (ELEM(c, SEP, ALTSEP, '\0')) {
+ if (prev - 1 != i) {
+ i += 1;
+ if (index_step == index) {
+ *r_offset = i;
+ *r_len = prev - i;
+ return true;
+ }
+ index_step -= 1;
+ }
+ if (c == '\0') {
+ break;
+ }
+ prev = i;
+ }
+ i -= 1;
+ }
+ return false;
+ }
+}
+
/* UNUSED */
#if 0
/**
diff --git a/source/blender/blenlib/intern/polyfill2d.c b/source/blender/blenlib/intern/polyfill2d.c
index 8d9881e4539..2969b0eccf4 100644
--- a/source/blender/blenlib/intern/polyfill2d.c
+++ b/source/blender/blenlib/intern/polyfill2d.c
@@ -21,8 +21,15 @@
/** \file blender/blenlib/intern/polyfill2d.c
* \ingroup bli
*
- * A simple implementation of the ear cutting algorithm
- * to triangulate simple polygons without holes.
+ * An ear clipping algorithm to triangulate single boundary polygons.
+ *
+ * Details:
+ *
+ * - The algorithm guarantees all triangles are assigned (number of coords - 2)
+ * and that triangles will have non-overlapping indices (even for degenerate geometry).
+ * - Self-intersections are considered degenerate (resulting triangles will overlap).
+ * - While multiple polygons aren't supported, holes can still be defined using *key-holes*
+ * (where the polygon doubles back on its self with *exactly* matching coordinates).
*
* \note
*
@@ -74,6 +81,12 @@ typedef signed char eSign;
#ifdef USE_KDTREE
/**
+ * Spatial optimization for point-in-triangle intersection checks.
+ * The simple version of this algorithm is ``O(n^2)`` complexity
+ * (every point needing to check the triangle defined by every other point),
+ * Using a binary-tree reduces the complexity to ``O(n log n)``
+ * plus some overhead of creating the tree.
+ *
* This is a single purpose KDTree based on BLI_kdtree with some modifications
* to better suit polyfill2d.
*
diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c
index ac73a981b45..fd24a00156d 100644
--- a/source/blender/blenlib/intern/rct.c
+++ b/source/blender/blenlib/intern/rct.c
@@ -351,6 +351,22 @@ void BLI_rcti_init(rcti *rect, int xmin, int xmax, int ymin, int ymax)
}
}
+void BLI_rctf_init_pt_radius(rctf *rect, const float xy[2], float size)
+{
+ rect->xmin = xy[0] - size;
+ rect->xmax = xy[0] + size;
+ rect->ymin = xy[1] - size;
+ rect->ymax = xy[1] + size;
+}
+
+void BLI_rcti_init_pt_radius(rcti *rect, const int xy[2], int size)
+{
+ rect->xmin = xy[0] - size;
+ rect->xmax = xy[0] + size;
+ rect->ymin = xy[1] - size;
+ rect->ymax = xy[1] + size;
+}
+
void BLI_rcti_init_minmax(rcti *rect)
{
rect->xmin = rect->ymin = INT_MAX;
diff --git a/source/blender/blenlib/intern/task.c b/source/blender/blenlib/intern/task.c
index fc2d9674c2f..297d0f0b310 100644
--- a/source/blender/blenlib/intern/task.c
+++ b/source/blender/blenlib/intern/task.c
@@ -48,6 +48,32 @@
*/
#define MEMPOOL_SIZE 256
+/* Number of tasks which are pushed directly to local thread queue.
+ *
+ * This allows thread to fetch next task without locking the whole queue.
+ */
+#define LOCALQUEUE_SIZE 1
+
+#ifndef NDEBUG
+# define ASSERT_THREAD_ID(scheduler, thread_id) \
+ do { \
+ if (!BLI_thread_is_main()) { \
+ TaskThread *thread = pthread_getspecific(scheduler->tls_id_key); \
+ if (thread == NULL) { \
+ BLI_assert(thread_id == 0); \
+ } \
+ else { \
+ BLI_assert(thread_id == thread->id); \
+ } \
+ } \
+ else { \
+ BLI_assert(thread_id == 0); \
+ } \
+ } while (false)
+#else
+# define ASSERT_THREAD_ID(scheduler, thread_id)
+#endif
+
typedef struct Task {
struct Task *next, *prev;
@@ -102,13 +128,16 @@ typedef struct TaskMemPoolStats {
} TaskMemPoolStats;
#endif
+typedef struct TaskThreadLocalStorage {
+ TaskMemPool task_mempool;
+ int num_local_queue;
+ Task *local_queue[LOCALQUEUE_SIZE];
+} TaskThreadLocalStorage;
+
struct TaskPool {
TaskScheduler *scheduler;
volatile size_t num;
- volatile size_t done;
- size_t num_threads;
- size_t currently_running_tasks;
ThreadMutex num_mutex;
ThreadCondition num_cond;
@@ -116,6 +145,11 @@ struct TaskPool {
ThreadMutex user_mutex;
volatile bool do_cancel;
+ volatile bool do_work;
+
+ volatile bool is_suspended;
+ ListBase suspended_queue;
+ size_t num_suspended;
/* If set, this pool may never be work_and_wait'ed, which means TaskScheduler
* has to use its special background fallback thread in case we are in
@@ -123,16 +157,10 @@ struct TaskPool {
*/
bool run_in_background;
- /* This pool is used for caching task pointers for thread id 0.
- * This could either point to a global scheduler's task_mempool[0] if the
- * pool is handled form the main thread or point to task_mempool_local
- * otherwise.
- *
- * This way we solve possible threading conflicts accessing same global
- * memory pool from multiple threads from which wait_work() is called.
+ /* This is a task scheduler's ID of a thread at which pool was constructed.
+ * It will be used to access task TLS.
*/
- TaskMemPool *task_mempool;
- TaskMemPool task_mempool_local;
+ int thread_id;
#ifdef DEBUG_STATS
TaskMemPoolStats *mempool_stats;
@@ -142,7 +170,6 @@ struct TaskPool {
struct TaskScheduler {
pthread_t *threads;
struct TaskThread *task_threads;
- TaskMemPool *task_mempool;
int num_threads;
bool background_thread_only;
@@ -151,15 +178,19 @@ struct TaskScheduler {
ThreadCondition queue_cond;
volatile bool do_exit;
+
+ /* NOTE: In pthread's TLS we store the whole TaskThread structure. */
+ pthread_key_t tls_id_key;
};
typedef struct TaskThread {
TaskScheduler *scheduler;
int id;
+ TaskThreadLocalStorage tls;
} TaskThread;
/* Helper */
-static void task_data_free(Task *task, const int thread_id)
+BLI_INLINE void task_data_free(Task *task, const int thread_id)
{
if (task->free_taskdata) {
if (task->freedata) {
@@ -171,28 +202,42 @@ static void task_data_free(Task *task, const int thread_id)
}
}
-BLI_INLINE TaskMemPool *get_task_mempool(TaskPool *pool, const int thread_id)
+BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool,
+ const int thread_id)
{
+ TaskScheduler *scheduler = pool->scheduler;
+ BLI_assert(thread_id >= 0);
+ BLI_assert(thread_id <= scheduler->num_threads);
if (thread_id == 0) {
- return pool->task_mempool;
+ return &scheduler->task_threads[pool->thread_id].tls;
+ }
+ return &scheduler->task_threads[thread_id].tls;
+}
+
+BLI_INLINE void free_task_tls(TaskThreadLocalStorage *tls)
+{
+ TaskMemPool *task_mempool = &tls->task_mempool;
+ for (int i = 0; i < task_mempool->num_tasks; ++i) {
+ MEM_freeN(task_mempool->tasks[i]);
}
- return &pool->scheduler->task_mempool[thread_id];
}
static Task *task_alloc(TaskPool *pool, const int thread_id)
{
- assert(thread_id <= pool->scheduler->num_threads);
+ BLI_assert(thread_id <= pool->scheduler->num_threads);
if (thread_id != -1) {
- assert(thread_id >= 0);
- TaskMemPool *mem_pool = get_task_mempool(pool, thread_id);
+ BLI_assert(thread_id >= 0);
+ BLI_assert(thread_id <= pool->scheduler->num_threads);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ TaskMemPool *task_mempool = &tls->task_mempool;
/* Try to re-use task memory from a thread local storage. */
- if (mem_pool->num_tasks > 0) {
- --mem_pool->num_tasks;
+ if (task_mempool->num_tasks > 0) {
+ --task_mempool->num_tasks;
/* Success! We've just avoided task allocation. */
#ifdef DEBUG_STATS
pool->mempool_stats[thread_id].num_reuse++;
#endif
- return mem_pool->tasks[mem_pool->num_tasks];
+ return task_mempool->tasks[task_mempool->num_tasks];
}
/* We are doomed to allocate new task data. */
#ifdef DEBUG_STATS
@@ -205,13 +250,14 @@ static Task *task_alloc(TaskPool *pool, const int thread_id)
static void task_free(TaskPool *pool, Task *task, const int thread_id)
{
task_data_free(task, thread_id);
- assert(thread_id >= 0);
- assert(thread_id <= pool->scheduler->num_threads);
- TaskMemPool *mem_pool = get_task_mempool(pool, thread_id);
- if (mem_pool->num_tasks < MEMPOOL_SIZE - 1) {
+ BLI_assert(thread_id >= 0);
+ BLI_assert(thread_id <= pool->scheduler->num_threads);
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ TaskMemPool *task_mempool = &tls->task_mempool;
+ if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) {
/* Successfully allowed the task to be re-used later. */
- mem_pool->tasks[mem_pool->num_tasks] = task;
- ++mem_pool->num_tasks;
+ task_mempool->tasks[task_mempool->num_tasks] = task;
+ ++task_mempool->num_tasks;
}
else {
/* Local storage saturated, no other way than just discard
@@ -237,8 +283,6 @@ static void task_pool_num_decrease(TaskPool *pool, size_t done)
BLI_assert(pool->num >= done);
pool->num -= done;
- atomic_sub_and_fetch_z(&pool->currently_running_tasks, done);
- pool->done += done;
if (pool->num == 0)
BLI_condition_notify_all(&pool->num_cond);
@@ -246,11 +290,11 @@ static void task_pool_num_decrease(TaskPool *pool, size_t done)
BLI_mutex_unlock(&pool->num_mutex);
}
-static void task_pool_num_increase(TaskPool *pool)
+static void task_pool_num_increase(TaskPool *pool, size_t new)
{
BLI_mutex_lock(&pool->num_mutex);
- pool->num++;
+ pool->num += new;
BLI_condition_notify_all(&pool->num_cond);
BLI_mutex_unlock(&pool->num_mutex);
@@ -292,17 +336,10 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
continue;
}
- if (atomic_add_and_fetch_z(&pool->currently_running_tasks, 1) <= pool->num_threads ||
- pool->num_threads == 0)
- {
- *task = current_task;
- found_task = true;
- BLI_remlink(&scheduler->queue, *task);
- break;
- }
- else {
- atomic_sub_and_fetch_z(&pool->currently_running_tasks, 1);
- }
+ *task = current_task;
+ found_task = true;
+ BLI_remlink(&scheduler->queue, *task);
+ break;
}
if (!found_task)
BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex);
@@ -313,13 +350,34 @@ static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task
return true;
}
+BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls,
+ const int thread_id)
+{
+ while (tls->num_local_queue > 0) {
+ /* We pop task from queue before handling it so handler of the task can
+ * push next job to the local queue.
+ */
+ tls->num_local_queue--;
+ Task *local_task = tls->local_queue[tls->num_local_queue];
+ /* TODO(sergey): Double-check work_and_wait() doesn't handle other's
+ * pool tasks.
+ */
+ TaskPool *local_pool = local_task->pool;
+ local_task->run(local_pool, local_task->taskdata, thread_id);
+ task_free(local_pool, local_task, thread_id);
+ }
+}
+
static void *task_scheduler_thread_run(void *thread_p)
{
TaskThread *thread = (TaskThread *) thread_p;
+ TaskThreadLocalStorage *tls = &thread->tls;
TaskScheduler *scheduler = thread->scheduler;
int thread_id = thread->id;
Task *task;
+ pthread_setspecific(scheduler->tls_id_key, thread);
+
/* keep popping off tasks */
while (task_scheduler_thread_wait_pop(scheduler, &task)) {
TaskPool *pool = task->pool;
@@ -330,6 +388,9 @@ static void *task_scheduler_thread_run(void *thread_p)
/* delete task */
task_free(pool, task, thread_id);
+ /* Handle all tasks from local queue. */
+ handle_local_queue(tls, thread_id);
+
/* notify pool task was done */
task_pool_num_decrease(pool, 1);
}
@@ -359,20 +420,24 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
/* Add background-only thread if needed. */
if (num_threads == 0) {
- scheduler->background_thread_only = true;
- num_threads = 1;
+ scheduler->background_thread_only = true;
+ num_threads = 1;
}
+ scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * (num_threads + 1),
+ "TaskScheduler task threads");
+
+ pthread_key_create(&scheduler->tls_id_key, NULL);
+
/* launch threads that will be waiting for work */
if (num_threads > 0) {
int i;
scheduler->num_threads = num_threads;
scheduler->threads = MEM_callocN(sizeof(pthread_t) * num_threads, "TaskScheduler threads");
- scheduler->task_threads = MEM_callocN(sizeof(TaskThread) * num_threads, "TaskScheduler task threads");
for (i = 0; i < num_threads; i++) {
- TaskThread *thread = &scheduler->task_threads[i];
+ TaskThread *thread = &scheduler->task_threads[i + 1];
thread->scheduler = scheduler;
thread->id = i + 1;
@@ -380,9 +445,6 @@ TaskScheduler *BLI_task_scheduler_create(int num_threads)
fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads);
}
}
-
- scheduler->task_mempool = MEM_callocN(sizeof(*scheduler->task_mempool) * (num_threads + 1),
- "TaskScheduler task_mempool");
}
return scheduler;
@@ -398,6 +460,8 @@ void BLI_task_scheduler_free(TaskScheduler *scheduler)
BLI_condition_notify_all(&scheduler->queue_cond);
BLI_mutex_unlock(&scheduler->queue_mutex);
+ pthread_key_delete(scheduler->tls_id_key);
+
/* delete threads */
if (scheduler->threads) {
int i;
@@ -412,17 +476,12 @@ void BLI_task_scheduler_free(TaskScheduler *scheduler)
/* Delete task thread data */
if (scheduler->task_threads) {
- MEM_freeN(scheduler->task_threads);
- }
-
- /* Delete task memory pool */
- if (scheduler->task_mempool) {
- for (int i = 0; i <= scheduler->num_threads; ++i) {
- for (int j = 0; j < scheduler->task_mempool[i].num_tasks; ++j) {
- MEM_freeN(scheduler->task_mempool[i].tasks[j]);
- }
+ for (int i = 0; i < scheduler->num_threads + 1; ++i) {
+ TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls;
+ free_task_tls(tls);
}
- MEM_freeN(scheduler->task_mempool);
+
+ MEM_freeN(scheduler->task_threads);
}
/* delete leftover tasks */
@@ -445,7 +504,7 @@ int BLI_task_scheduler_num_threads(TaskScheduler *scheduler)
static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority)
{
- task_pool_num_increase(task->pool);
+ task_pool_num_increase(task->pool, 1);
/* add task to queue */
BLI_mutex_lock(&scheduler->queue_mutex);
@@ -471,7 +530,7 @@ static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
nexttask = task->next;
if (task->pool == pool) {
- task_data_free(task, 0);
+ task_data_free(task, pool->thread_id);
BLI_freelinkN(&scheduler->queue, task);
done++;
@@ -486,7 +545,10 @@ static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool)
/* Task Pool */
-static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, const bool is_background)
+static TaskPool *task_pool_create_ex(TaskScheduler *scheduler,
+ void *userdata,
+ const bool is_background,
+ const bool is_suspended)
{
TaskPool *pool = MEM_mallocN(sizeof(TaskPool), "TaskPool");
@@ -504,10 +566,11 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, c
pool->scheduler = scheduler;
pool->num = 0;
- pool->done = 0;
- pool->num_threads = 0;
- pool->currently_running_tasks = 0;
pool->do_cancel = false;
+ pool->do_work = false;
+ pool->is_suspended = is_suspended;
+ pool->num_suspended = 0;
+ pool->suspended_queue.first = pool->suspended_queue.last = NULL;
pool->run_in_background = is_background;
BLI_mutex_init(&pool->num_mutex);
@@ -517,11 +580,21 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, c
BLI_mutex_init(&pool->user_mutex);
if (BLI_thread_is_main()) {
- pool->task_mempool = scheduler->task_mempool;
+ pool->thread_id = 0;
}
else {
- pool->task_mempool = &pool->task_mempool_local;
- pool->task_mempool_local.num_tasks = 0;
+ TaskThread *thread = pthread_getspecific(scheduler->tls_id_key);
+ /* NOTE: It is possible that pool is created from non-main thread
+ * which isn't a scheduler thread. In this case pthread's TLS will
+ * be NULL and we can safely consider thread id 0 for the main
+ * thread of this pool (the one which does wort_and_wait()).
+ */
+ if (thread == NULL) {
+ pool->thread_id = 0;
+ }
+ else {
+ pool->thread_id = thread->id;
+ }
}
#ifdef DEBUG_STATS
@@ -548,7 +621,7 @@ static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, void *userdata, c
*/
TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
{
- return task_pool_create_ex(scheduler, userdata, false);
+ return task_pool_create_ex(scheduler, userdata, false, false);
}
/**
@@ -563,25 +636,28 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata)
*/
TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, void *userdata)
{
- return task_pool_create_ex(scheduler, userdata, true);
+ return task_pool_create_ex(scheduler, userdata, true, false);
+}
+
+/**
+ * Similar to BLI_task_pool_create() but does not schedule any tasks for execution
+ * for until BLI_task_pool_work_and_wait() is called. This helps reducing therading
+ * overhead when pushing huge amount of small initial tasks from the main thread.
+ */
+TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, void *userdata)
+{
+ return task_pool_create_ex(scheduler, userdata, false, true);
}
void BLI_task_pool_free(TaskPool *pool)
{
- BLI_task_pool_stop(pool);
+ BLI_task_pool_cancel(pool);
BLI_mutex_end(&pool->num_mutex);
BLI_condition_end(&pool->num_cond);
BLI_mutex_end(&pool->user_mutex);
- /* Free local memory pool, those pointers are lost forever. */
- if (pool->task_mempool == &pool->task_mempool_local) {
- for (int i = 0; i < pool->task_mempool_local.num_tasks; i++) {
- MEM_freeN(pool->task_mempool_local.tasks[i]);
- }
- }
-
#ifdef DEBUG_STATS
printf("Thread ID Allocated Reused Discarded\n");
for (int i = 0; i < pool->scheduler->num_threads + 1; ++i) {
@@ -612,6 +688,25 @@ static void task_pool_push(
task->freedata = freedata;
task->pool = pool;
+ if (pool->is_suspended) {
+ BLI_addhead(&pool->suspended_queue, task);
+ atomic_fetch_and_add_z(&pool->num_suspended, 1);
+ return;
+ }
+
+ if (thread_id != -1 &&
+ (thread_id != pool->thread_id || pool->do_work))
+ {
+ ASSERT_THREAD_ID(pool->scheduler, thread_id);
+
+ TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id);
+ if (tls->num_local_queue < LOCALQUEUE_SIZE) {
+ tls->local_queue[tls->num_local_queue] = task;
+ tls->num_local_queue++;
+ return;
+ }
+ }
+
task_scheduler_push(pool->scheduler, task, priority);
}
@@ -636,8 +731,25 @@ void BLI_task_pool_push_from_thread(TaskPool *pool, TaskRunFunction run,
void BLI_task_pool_work_and_wait(TaskPool *pool)
{
+ TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id);
TaskScheduler *scheduler = pool->scheduler;
+ if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) {
+ if (pool->num_suspended) {
+ task_pool_num_increase(pool, pool->num_suspended);
+ BLI_mutex_lock(&scheduler->queue_mutex);
+
+ BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue);
+
+ BLI_condition_notify_all(&scheduler->queue_cond);
+ BLI_mutex_unlock(&scheduler->queue_mutex);
+ }
+ }
+
+ pool->do_work = true;
+
+ ASSERT_THREAD_ID(pool->scheduler, pool->thread_id);
+
BLI_mutex_lock(&pool->num_mutex);
while (pool->num != 0) {
@@ -651,16 +763,12 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* find task from this pool. if we get a task from another pool,
* we can get into deadlock */
- if (pool->num_threads == 0 ||
- pool->currently_running_tasks < pool->num_threads)
- {
- for (task = scheduler->queue.first; task; task = task->next) {
- if (task->pool == pool) {
- work_task = task;
- found_task = true;
- BLI_remlink(&scheduler->queue, task);
- break;
- }
+ for (task = scheduler->queue.first; task; task = task->next) {
+ if (task->pool == pool) {
+ work_task = task;
+ found_task = true;
+ BLI_remlink(&scheduler->queue, task);
+ break;
}
}
@@ -669,11 +777,13 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
/* if found task, do it, otherwise wait until other tasks are done */
if (found_task) {
/* run task */
- atomic_add_and_fetch_z(&pool->currently_running_tasks, 1);
- work_task->run(pool, work_task->taskdata, 0);
+ work_task->run(pool, work_task->taskdata, pool->thread_id);
/* delete task */
- task_free(pool, task, 0);
+ task_free(pool, task, pool->thread_id);
+
+ /* Handle all tasks from local queue. */
+ handle_local_queue(tls, pool->thread_id);
/* notify pool task was done */
task_pool_num_decrease(pool, 1);
@@ -688,22 +798,8 @@ void BLI_task_pool_work_and_wait(TaskPool *pool)
}
BLI_mutex_unlock(&pool->num_mutex);
-}
-int BLI_pool_get_num_threads(TaskPool *pool)
-{
- if (pool->num_threads != 0) {
- return pool->num_threads;
- }
- else {
- return BLI_task_scheduler_num_threads(pool->scheduler);
- }
-}
-
-void BLI_pool_set_num_threads(TaskPool *pool, int num_threads)
-{
- /* NOTE: Don't try to modify threads while tasks are running! */
- pool->num_threads = num_threads;
+ handle_local_queue(tls, pool->thread_id);
}
void BLI_task_pool_cancel(TaskPool *pool)
@@ -721,13 +817,6 @@ void BLI_task_pool_cancel(TaskPool *pool)
pool->do_cancel = false;
}
-void BLI_task_pool_stop(TaskPool *pool)
-{
- task_scheduler_clear(pool->scheduler, pool);
-
- BLI_assert(pool->num == 0);
-}
-
bool BLI_task_pool_canceled(TaskPool *pool)
{
return pool->do_cancel;
@@ -743,11 +832,6 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool)
return &pool->user_mutex;
}
-size_t BLI_task_pool_tasks_done(TaskPool *pool)
-{
- return pool->done;
-}
-
/* Parallel range routines */
/**
@@ -783,7 +867,7 @@ BLI_INLINE bool parallel_range_next_iter_get(
int * __restrict iter, int * __restrict count)
{
uint32_t uval = atomic_fetch_and_add_uint32((uint32_t *)(&state->iter), state->chunk_size);
- int previter = *(int32_t*)&uval;
+ int previter = *(int32_t *)&uval;
*iter = previter;
*count = max_ii(0, min_ii(state->chunk_size, state->stop - previter));
@@ -918,7 +1002,8 @@ static void task_parallel_range_ex(
BLI_task_pool_push_from_thread(task_pool,
parallel_range_func,
userdata_chunk_local, false,
- TASK_PRIORITY_HIGH, 0);
+ TASK_PRIORITY_HIGH,
+ task_pool->thread_id);
}
BLI_task_pool_work_and_wait(task_pool);
@@ -1124,7 +1209,8 @@ void BLI_task_parallel_listbase(
BLI_task_pool_push_from_thread(task_pool,
parallel_listbase_func,
NULL, false,
- TASK_PRIORITY_HIGH, 0);
+ TASK_PRIORITY_HIGH,
+ task_pool->thread_id);
}
BLI_task_pool_work_and_wait(task_pool);
diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c
index b60981802aa..77da3be0600 100644
--- a/source/blender/blenlib/intern/threads.c
+++ b/source/blender/blenlib/intern/threads.c
@@ -54,6 +54,8 @@
# include <sys/time.h>
#endif
+#include "atomic_ops.h"
+
#if defined(__APPLE__) && defined(_OPENMP) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) && !defined(__clang__)
# define USE_APPLE_OMP_FIX
#endif
@@ -124,7 +126,7 @@ static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t _view3d_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_t mainid;
-static int thread_levels = 0; /* threads can be invoked inside threads */
+static unsigned int thread_levels = 0; /* threads can be invoked inside threads */
static int num_threads_override = 0;
/* just a max for security reasons */
@@ -198,9 +200,9 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
tslot->avail = 1;
}
}
-
- BLI_spin_lock(&_malloc_lock);
- if (thread_levels == 0) {
+
+ unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1);
+ if (level == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
#ifdef USE_APPLE_OMP_FIX
@@ -210,9 +212,6 @@ void BLI_init_threads(ListBase *threadbase, void *(*do_thread)(void *), int tot)
thread_tls_data = pthread_getspecific(gomp_tls_key);
#endif
}
-
- thread_levels++;
- BLI_spin_unlock(&_malloc_lock);
}
/* amount of available threads */
@@ -331,11 +330,10 @@ void BLI_end_threads(ListBase *threadbase)
BLI_freelistN(threadbase);
}
- BLI_spin_lock(&_malloc_lock);
- thread_levels--;
- if (thread_levels == 0)
+ unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1);
+ if (level == 0) {
MEM_set_lock_callback(NULL, NULL);
- BLI_spin_unlock(&_malloc_lock);
+ }
}
/* System Information */
@@ -812,26 +810,17 @@ void BLI_thread_queue_wait_finish(ThreadQueue *queue)
void BLI_begin_threaded_malloc(void)
{
- /* Used for debug only */
- /* BLI_assert(thread_levels >= 0); */
-
- BLI_spin_lock(&_malloc_lock);
- if (thread_levels == 0) {
+ unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1);
+ if (level == 0) {
MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread);
}
- thread_levels++;
- BLI_spin_unlock(&_malloc_lock);
}
void BLI_end_threaded_malloc(void)
{
- /* Used for debug only */
- /* BLI_assert(thread_levels >= 0); */
-
- BLI_spin_lock(&_malloc_lock);
- thread_levels--;
- if (thread_levels == 0)
+ unsigned int level = atomic_sub_and_fetch_u(&thread_levels, 1);
+ if (level == 0) {
MEM_set_lock_callback(NULL, NULL);
- BLI_spin_unlock(&_malloc_lock);
+ }
}
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index c85cf128643..e6fc4703248 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -71,11 +71,25 @@ typedef struct BlendFileData {
BlenFileType type;
} BlendFileData;
-BlendFileData *BLO_read_from_file(const char *filepath, struct ReportList *reports);
-BlendFileData *BLO_read_from_memory(const void *mem, int memsize, struct ReportList *reports);
+
+/* skip reading some data-block types (may want to skip screen data too). */
+typedef enum eBLOReadSkip {
+ BLO_READ_SKIP_NONE = 0,
+ BLO_READ_SKIP_USERDEF = (1 << 0),
+ BLO_READ_SKIP_DATA = (1 << 1),
+} eBLOReadSkip;
+#define BLO_READ_SKIP_ALL \
+ (BLO_READ_SKIP_USERDEF | BLO_READ_SKIP_DATA)
+
+BlendFileData *BLO_read_from_file(
+ const char *filepath,
+ struct ReportList *reports, eBLOReadSkip skip_flag);
+BlendFileData *BLO_read_from_memory(
+ const void *mem, int memsize,
+ struct ReportList *reports, eBLOReadSkip skip_flag);
BlendFileData *BLO_read_from_memfile(
struct Main *oldmain, const char *filename, struct MemFile *memfile,
- struct ReportList *reports);
+ struct ReportList *reports, eBLOReadSkip skip_flag);
void BLO_blendfiledata_free(BlendFileData *bfd);
diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt
index e40692f4a88..d77c7388929 100644
--- a/source/blender/blenloader/CMakeLists.txt
+++ b/source/blender/blenloader/CMakeLists.txt
@@ -70,6 +70,12 @@ if(WITH_BUILDINFO)
add_definitions(-DWITH_BUILDINFO)
endif()
+if(WITH_PYTHON)
+ if(WITH_PYTHON_SECURITY)
+ add_definitions(-DWITH_PYTHON_SECURITY)
+ endif()
+endif()
+
if(WITH_INTERNATIONAL)
add_definitions(-DWITH_INTERNATIONAL)
endif()
diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c
index be893177b3b..73109413271 100644
--- a/source/blender/blenloader/intern/readblenentry.c
+++ b/source/blender/blenloader/intern/readblenentry.c
@@ -317,7 +317,9 @@ void BLO_blendhandle_close(BlendHandle *bh)
* \param reports If the return value is NULL, errors indicating the cause of the failure.
* \return The data of the file.
*/
-BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
+BlendFileData *BLO_read_from_file(
+ const char *filepath,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -325,6 +327,7 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
fd = blo_openblenderfile(filepath, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
bfd = blo_read_file_internal(fd, filepath);
blo_freefiledata(fd);
}
@@ -341,7 +344,9 @@ BlendFileData *BLO_read_from_file(const char *filepath, ReportList *reports)
* \param reports If the return value is NULL, errors indicating the cause of the failure.
* \return The data of the file.
*/
-BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *reports)
+BlendFileData *BLO_read_from_memory(
+ const void *mem, int memsize,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -349,6 +354,7 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re
fd = blo_openblendermemory(mem, memsize, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
bfd = blo_read_file_internal(fd, "");
blo_freefiledata(fd);
}
@@ -362,7 +368,9 @@ BlendFileData *BLO_read_from_memory(const void *mem, int memsize, ReportList *re
* \param oldmain old main, from which we will keep libraries and other datablocks that should not have changed.
* \param filename current file, only for retrieving library data.
*/
-BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFile *memfile, ReportList *reports)
+BlendFileData *BLO_read_from_memfile(
+ Main *oldmain, const char *filename, MemFile *memfile,
+ ReportList *reports, eBLOReadSkip skip_flags)
{
BlendFileData *bfd = NULL;
FileData *fd;
@@ -371,6 +379,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
fd = blo_openblendermemfile(memfile, reports);
if (fd) {
fd->reports = reports;
+ fd->skip_flags = skip_flags;
BLI_strncpy(fd->relabase, filename, sizeof(fd->relabase));
/* clear ob->proxy_from pointers in old main */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 9af85cc9ee9..83d6b0251ce 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -103,8 +103,6 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
-#include "RNA_access.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_endian_switch.h"
@@ -128,6 +126,7 @@
#include "BKE_fcurve.h"
#include "BKE_global.h" // for G
#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h" // for which_libbase
#include "BKE_library_idmap.h"
#include "BKE_library_query.h"
@@ -2195,19 +2194,19 @@ static void direct_link_curvemapping(FileData *fd, CurveMapping *cumap)
/* library brush linking after fileread */
static void lib_link_brush(FileData *fd, Main *main)
{
- Brush *brush;
-
/* only link ID pointers */
- for (brush = main->brush.first; brush; brush = brush->id.next) {
+ for (Brush *brush = main->brush.first; brush; brush = brush->id.next) {
if (brush->id.tag & LIB_TAG_NEED_LINK) {
- brush->id.tag &= ~LIB_TAG_NEED_LINK;
-
+ IDP_LibLinkProperty(brush->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
/* brush->(mask_)mtex.obj is ignored on purpose? */
brush->mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mtex.tex);
brush->mask_mtex.tex = newlibadr_us(fd, brush->id.lib, brush->mask_mtex.tex);
brush->clone.image = newlibadr(fd, brush->id.lib, brush->clone.image);
brush->toggle_brush = newlibadr(fd, brush->id.lib, brush->toggle_brush);
brush->paint_curve = newlibadr_us(fd, brush->id.lib, brush->paint_curve);
+
+ brush->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -2230,13 +2229,13 @@ static void direct_link_brush(FileData *fd, Brush *brush)
}
/* ************ READ Palette *************** */
-static void lib_link_palette(FileData *UNUSED(fd), Main *main)
+static void lib_link_palette(FileData *fd, Main *main)
{
- Palette *palette;
-
/* only link ID pointers */
- for (palette = main->palettes.first; palette; palette = palette->id.next) {
+ for (Palette *palette = main->palettes.first; palette; palette = palette->id.next) {
if (palette->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(palette->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
palette->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -2248,13 +2247,13 @@ static void direct_link_palette(FileData *fd, Palette *palette)
link_list(fd, &palette->colors);
}
-static void lib_link_paint_curve(FileData *UNUSED(fd), Main *main)
+static void lib_link_paint_curve(FileData *fd, Main *main)
{
- PaintCurve *pc;
-
/* only link ID pointers */
- for (pc = main->paintcurves.first; pc; pc = pc->id.next) {
+ for (PaintCurve *pc = main->paintcurves.first; pc; pc = pc->id.next) {
if (pc->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(pc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
pc->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -2506,15 +2505,12 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
static void lib_link_action(FileData *fd, Main *main)
{
- bAction *act;
- bActionChannel *chan;
-
- for (act = main->action.first; act; act = act->id.next) {
+ for (bAction *act = main->action.first; act; act = act->id.next) {
if (act->id.tag & LIB_TAG_NEED_LINK) {
- act->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(act->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
// XXX deprecated - old animation system <<<
- for (chan=act->chanbase.first; chan; chan=chan->next) {
+ for (bActionChannel *chan = act->chanbase.first; chan; chan = chan->next) {
chan->ipo = newlibadr_us(fd, act->id.lib, chan->ipo);
lib_link_constraint_channels(fd, &act->id, &chan->constraintChannels);
}
@@ -2527,6 +2523,8 @@ static void lib_link_action(FileData *fd, Main *main)
marker->camera = newlibadr(fd, act->id.lib, marker->camera);
}
}
+
+ act->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -2713,26 +2711,20 @@ static void direct_link_animdata(FileData *fd, AnimData *adt)
static void lib_link_cachefiles(FileData *fd, Main *bmain)
{
- CacheFile *cache_file;
-
/* only link ID pointers */
- for (cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
+ for (CacheFile *cache_file = bmain->cachefiles.first; cache_file; cache_file = cache_file->id.next) {
if (cache_file->id.tag & LIB_TAG_NEED_LINK) {
- cache_file->id.tag &= ~LIB_TAG_NEED_LINK;
- }
-
- BLI_listbase_clear(&cache_file->object_paths);
- cache_file->handle = NULL;
- cache_file->handle_mutex = NULL;
-
- if (cache_file->adt) {
+ IDP_LibLinkProperty(cache_file->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &cache_file->id, cache_file->adt);
+
+ cache_file->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
static void direct_link_cachefile(FileData *fd, CacheFile *cache_file)
{
+ BLI_listbase_clear(&cache_file->object_paths);
cache_file->handle = NULL;
cache_file->handle_mutex = NULL;
@@ -2769,6 +2761,7 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
bNode *node;
bNodeSocket *sock;
+ IDP_LibLinkProperty(ntree->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &ntree->id, ntree->adt);
ntree->gpd = newlibadr_us(fd, id->lib, ntree->gpd);
@@ -2778,30 +2771,37 @@ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree)
* of library blocks that implement this.*/
IDP_LibLinkProperty(node->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- node->id= newlibadr_us(fd, id->lib, node->id);
+ node->id = newlibadr_us(fd, id->lib, node->id);
- for (sock = node->inputs.first; sock; sock = sock->next)
+ for (sock = node->inputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_node_socket(fd, id, sock);
- for (sock = node->outputs.first; sock; sock = sock->next)
+ }
+ for (sock = node->outputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_node_socket(fd, id, sock);
+ }
}
- for (sock = ntree->inputs.first; sock; sock = sock->next)
+ for (sock = ntree->inputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_node_socket(fd, id, sock);
- for (sock = ntree->outputs.first; sock; sock = sock->next)
+ }
+ for (sock = ntree->outputs.first; sock; sock = sock->next) {
+ IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_node_socket(fd, id, sock);
+ }
}
/* library ntree linking after fileread */
static void lib_link_nodetree(FileData *fd, Main *main)
{
- bNodeTree *ntree;
-
/* only link ID pointers */
- for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
+ for (bNodeTree *ntree = main->nodetree.first; ntree; ntree = ntree->id.next) {
if (ntree->id.tag & LIB_TAG_NEED_LINK) {
- ntree->id.tag &= ~LIB_TAG_NEED_LINK;
lib_link_ntree(fd, &ntree->id, ntree);
+
+ ntree->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -3316,11 +3316,11 @@ static void lib_link_pose(FileData *fd, Main *bmain, Object *ob, bPose *pose)
static void lib_link_armature(FileData *fd, Main *main)
{
- bArmature *arm;
-
- for (arm = main->armature.first; arm; arm = arm->id.next) {
+ for (bArmature *arm = main->armature.first; arm; arm = arm->id.next) {
if (arm->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(arm->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &arm->id, arm->adt);
+
arm->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3365,14 +3365,13 @@ static void direct_link_armature(FileData *fd, bArmature *arm)
static void lib_link_camera(FileData *fd, Main *main)
{
- Camera *ca;
-
- for (ca = main->camera.first; ca; ca = ca->id.next) {
+ for (Camera *ca = main->camera.first; ca; ca = ca->id.next) {
if (ca->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(ca->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &ca->id, ca->adt);
ca->ipo = newlibadr_us(fd, ca->id.lib, ca->ipo); // XXX deprecated - old animation system
-
+
ca->dof_ob = newlibadr(fd, ca->id.lib, ca->dof_ob);
ca->id.tag &= ~LIB_TAG_NEED_LINK;
@@ -3391,16 +3390,13 @@ static void direct_link_camera(FileData *fd, Camera *ca)
static void lib_link_lamp(FileData *fd, Main *main)
{
- Lamp *la;
- MTex *mtex;
- int a;
-
- for (la = main->lamp.first; la; la = la->id.next) {
+ for (Lamp *la = main->lamp.first; la; la = la->id.next) {
if (la->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(la->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &la->id, la->adt);
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = la->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = la->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, la->id.lib, mtex->tex);
mtex->object = newlibadr(fd, la->id.lib, mtex->object);
@@ -3457,17 +3453,11 @@ void blo_do_versions_key_uidgen(Key *key)
static void lib_link_key(FileData *fd, Main *main)
{
- Key *key;
-
- for (key = main->key.first; key; key = key->id.next) {
- /*check if we need to generate unique ids for the shapekeys*/
- if (!key->uidgen) {
- blo_do_versions_key_uidgen(key);
- }
-
+ for (Key *key = main->key.first; key; key = key->id.next) {
BLI_assert((key->id.tag & LIB_TAG_EXTERN) == 0);
if (key->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(key->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &key->id, key->adt);
key->ipo = newlibadr_us(fd, key->id.lib, key->ipo); // XXX deprecated - old animation system
@@ -3530,15 +3520,14 @@ static void direct_link_key(FileData *fd, Key *key)
static void lib_link_mball(FileData *fd, Main *main)
{
- MetaBall *mb;
- int a;
-
- for (mb = main->mball.first; mb; mb = mb->id.next) {
+ for (MetaBall *mb = main->mball.first; mb; mb = mb->id.next) {
if (mb->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(mb->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &mb->id, mb->adt);
- for (a = 0; a < mb->totcol; a++)
+ for (int a = 0; a < mb->totcol; a++) {
mb->mat[a] = newlibadr_us(fd, mb->id.lib, mb->mat[a]);
+ }
mb->ipo = newlibadr_us(fd, mb->id.lib, mb->ipo); // XXX deprecated - old animation system
@@ -3567,18 +3556,15 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
static void lib_link_world(FileData *fd, Main *main)
{
- World *wrld;
- MTex *mtex;
- int a;
-
- for (wrld = main->world.first; wrld; wrld = wrld->id.next) {
+ for (World *wrld = main->world.first; wrld; wrld = wrld->id.next) {
if (wrld->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(wrld->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &wrld->id, wrld->adt);
wrld->ipo = newlibadr_us(fd, wrld->id.lib, wrld->ipo); // XXX deprecated - old animation system
- for (a=0; a < MAX_MTEX; a++) {
- mtex = wrld->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = wrld->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, wrld->id.lib, mtex->tex);
mtex->object = newlibadr(fd, wrld->id.lib, mtex->object);
@@ -3619,12 +3605,12 @@ static void direct_link_world(FileData *fd, World *wrld)
/* ************ READ VFONT ***************** */
-static void lib_link_vfont(FileData *UNUSED(fd), Main *main)
+static void lib_link_vfont(FileData *fd, Main *main)
{
- VFont *vf;
-
- for (vf = main->vfont.first; vf; vf = vf->id.next) {
+ for (VFont *vf = main->vfont.first; vf; vf = vf->id.next) {
if (vf->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(vf->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
vf->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3639,12 +3625,12 @@ static void direct_link_vfont(FileData *fd, VFont *vf)
/* ************ READ TEXT ****************** */
-static void lib_link_text(FileData *UNUSED(fd), Main *main)
+static void lib_link_text(FileData *fd, Main *main)
{
- Text *text;
-
- for (text = main->text.first; text; text = text->id.next) {
+ for (Text *text = main->text.first; text; text = text->id.next) {
if (text->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(text->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
text->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -3693,9 +3679,7 @@ static void direct_link_text(FileData *fd, Text *text)
static void lib_link_image(FileData *fd, Main *main)
{
- Image *ima;
-
- for (ima = main->image.first; ima; ima = ima->id.next) {
+ for (Image *ima = main->image.first; ima; ima = ima->id.next) {
if (ima->id.tag & LIB_TAG_NEED_LINK) {
IDP_LibLinkProperty(ima->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
@@ -3762,15 +3746,14 @@ static void direct_link_image(FileData *fd, Image *ima)
static void lib_link_curve(FileData *fd, Main *main)
{
- Curve *cu;
- int a;
-
- for (cu = main->curve.first; cu; cu = cu->id.next) {
+ for (Curve *cu = main->curve.first; cu; cu = cu->id.next) {
if (cu->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(cu->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &cu->id, cu->adt);
- for (a = 0; a < cu->totcol; a++)
+ for (int a = 0; a < cu->totcol; a++) {
cu->mat[a] = newlibadr_us(fd, cu->id.lib, cu->mat[a]);
+ }
cu->bevobj = newlibadr(fd, cu->id.lib, cu->bevobj);
cu->taperobj = newlibadr(fd, cu->id.lib, cu->taperobj);
@@ -3855,10 +3838,9 @@ static void direct_link_curve(FileData *fd, Curve *cu)
static void lib_link_texture(FileData *fd, Main *main)
{
- Tex *tex;
-
- for (tex = main->tex.first; tex; tex = tex->id.next) {
+ for (Tex *tex = main->tex.first; tex; tex = tex->id.next) {
if (tex->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(tex->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &tex->id, tex->adt);
tex->ima = newlibadr_us(fd, tex->id.lib, tex->ima);
@@ -3934,12 +3916,9 @@ static void direct_link_texture(FileData *fd, Tex *tex)
static void lib_link_material(FileData *fd, Main *main)
{
- Material *ma;
- MTex *mtex;
- int a;
-
- for (ma = main->mat.first; ma; ma = ma->id.next) {
+ for (Material *ma = main->mat.first; ma; ma = ma->id.next) {
if (ma->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(ma->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &ma->id, ma->adt);
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
@@ -3949,8 +3928,8 @@ static void lib_link_material(FileData *fd, Main *main)
ma->ipo = newlibadr_us(fd, ma->id.lib, ma->ipo); // XXX deprecated - old animation system
ma->group = newlibadr_us(fd, ma->id.lib, ma->group);
- for (a = 0; a < MAX_MTEX; a++) {
- mtex = ma->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = ma->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, ma->id.lib, mtex->tex);
mtex->object = newlibadr(fd, ma->id.lib, mtex->object);
@@ -3970,7 +3949,6 @@ static void lib_link_material(FileData *fd, Main *main)
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
- MaterialEngineSettings *mes;
ma->adt = newdataadr(fd, ma->adt);
direct_link_animdata(fd, ma->adt);
@@ -3991,11 +3969,6 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
-
- link_list(fd, &ma->engines_settings);
- for (mes = ma->engines_settings.first; mes; mes = mes->next) {
- mes->data = newdataadr(fd, mes->data);
- }
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -4087,14 +4060,11 @@ static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd)
static void lib_link_particlesettings(FileData *fd, Main *main)
{
- ParticleSettings *part;
- ParticleDupliWeight *dw;
- MTex *mtex;
- int a;
-
- for (part = main->particle.first; part; part = part->id.next) {
+ for (ParticleSettings *part = main->particle.first; part; part = part->id.next) {
if (part->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(part->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &part->id, part->adt);
+
part->ipo = newlibadr_us(fd, part->id.lib, part->ipo); // XXX deprecated - old animation system
part->dup_ob = newlibadr(fd, part->id.lib, part->dup_ob);
@@ -4114,6 +4084,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
}
if (part->dupliweights.first && part->dup_group) {
+ ParticleDupliWeight *dw;
int index_ok = 0;
/* check for old files without indices (all indexes 0) */
if (BLI_listbase_is_single(&part->dupliweights)) {
@@ -4178,8 +4149,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
}
}
- for (a = 0; a < MAX_MTEX; a++) {
- mtex= part->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex= part->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, part->id.lib, mtex->tex);
mtex->object = newlibadr(fd, part->id.lib, mtex->object);
@@ -4687,10 +4658,9 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
static void lib_link_latt(FileData *fd, Main *main)
{
- Lattice *lt;
-
- for (lt = main->latt.first; lt; lt = lt->id.next) {
+ for (Lattice *lt = main->latt.first; lt; lt = lt->id.next) {
if (lt->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(lt->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &lt->id, lt->adt);
lt->ipo = newlibadr_us(fd, lt->id.lib, lt->ipo); // XXX deprecated - old animation system
@@ -4734,16 +4704,12 @@ static void lib_link_modifiers(FileData *fd, Object *ob)
static void lib_link_object(FileData *fd, Main *main)
{
- Object *ob;
- PartEff *paf;
- bSensor *sens;
- bController *cont;
- bActuator *act;
- void *poin;
- int warn=0, a;
-
- for (ob = main->object.first; ob; ob = ob->id.next) {
+ bool warn = false;
+
+ for (Object *ob = main->object.first; ob; ob = ob->id.next) {
if (ob->id.tag & LIB_TAG_NEED_LINK) {
+ int a;
+
IDP_LibLinkProperty(ob->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &ob->id, ob->adt);
@@ -4776,17 +4742,17 @@ static void lib_link_object(FileData *fd, Main *main)
}
ob->proxy_group = newlibadr(fd, ob->id.lib, ob->proxy_group);
- poin = ob->data;
+ void *poin = ob->data;
ob->data = newlibadr_us(fd, ob->id.lib, ob->data);
- if (ob->data==NULL && poin!=NULL) {
+ if (ob->data == NULL && poin != NULL) {
if (ob->id.lib)
printf("Can't find obdata of %s lib %s\n", ob->id.name + 2, ob->id.lib->name);
else
printf("Object %s lost data.\n", ob->id.name + 2);
ob->type = OB_EMPTY;
- warn = 1;
+ warn = true;
if (ob->pose) {
/* we can't call #BKE_pose_free() here because of library linking
@@ -4832,13 +4798,13 @@ static void lib_link_object(FileData *fd, Main *main)
lib_link_nlastrips(fd, &ob->id, &ob->nlastrips);
// >>> XXX deprecated - old animation system
- for (paf = ob->effect.first; paf; paf = paf->next) {
+ for (PartEff *paf = ob->effect.first; paf; paf = paf->next) {
if (paf->type == EFF_PARTICLE) {
paf->group = newlibadr_us(fd, ob->id.lib, paf->group);
}
}
- for (sens = ob->sensors.first; sens; sens = sens->next) {
+ for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) {
for (a = 0; a < sens->totlinks; a++)
sens->links[a] = newglobadr(fd, sens->links[a]);
@@ -4849,7 +4815,7 @@ static void lib_link_object(FileData *fd, Main *main)
}
}
- for (cont = ob->controllers.first; cont; cont = cont->next) {
+ for (bController *cont = ob->controllers.first; cont; cont = cont->next) {
for (a=0; a < cont->totlinks; a++)
cont->links[a] = newglobadr(fd, cont->links[a]);
@@ -4861,86 +4827,117 @@ static void lib_link_object(FileData *fd, Main *main)
cont->totslinks = 0;
}
- for (act = ob->actuators.first; act; act = act->next) {
- if (act->type == ACT_SOUND) {
- bSoundActuator *sa = act->data;
- sa->sound= newlibadr_us(fd, ob->id.lib, sa->sound);
- }
- else if (act->type == ACT_GAME) {
- /* bGameActuator *ga= act->data; */
- }
- else if (act->type == ACT_CAMERA) {
- bCameraActuator *ca = act->data;
- ca->ob= newlibadr(fd, ob->id.lib, ca->ob);
- }
- /* leave this one, it's obsolete but necessary to read for conversion */
- else if (act->type == ACT_ADD_OBJECT) {
- bAddObjectActuator *eoa = act->data;
- if (eoa) eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
- }
- else if (act->type == ACT_OBJECT) {
- bObjectActuator *oa = act->data;
- if (oa == NULL) {
- init_actuator(act);
+ for (bActuator *act = ob->actuators.first; act; act = act->next) {
+ switch (act->type) {
+ case ACT_SOUND:
+ {
+ bSoundActuator *sa = act->data;
+ sa->sound = newlibadr_us(fd, ob->id.lib, sa->sound);
+ break;
}
- else {
- oa->reference = newlibadr(fd, ob->id.lib, oa->reference);
+ case ACT_GAME:
+ /* bGameActuator *ga= act->data; */
+ break;
+ case ACT_CAMERA:
+ {
+ bCameraActuator *ca = act->data;
+ ca->ob = newlibadr(fd, ob->id.lib, ca->ob);
+ break;
}
- }
- else if (act->type == ACT_EDIT_OBJECT) {
- bEditObjectActuator *eoa = act->data;
- if (eoa == NULL) {
- init_actuator(act);
+ /* leave this one, it's obsolete but necessary to read for conversion */
+ case ACT_ADD_OBJECT:
+ {
+ bAddObjectActuator *eoa = act->data;
+ if (eoa)
+ eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob);
+ break;
}
- else {
- eoa->ob= newlibadr(fd, ob->id.lib, eoa->ob);
- eoa->me= newlibadr(fd, ob->id.lib, eoa->me);
+ case ACT_OBJECT:
+ {
+ bObjectActuator *oa = act->data;
+ if (oa == NULL) {
+ init_actuator(act);
+ }
+ else {
+ oa->reference = newlibadr(fd, ob->id.lib, oa->reference);
+ }
+ break;
}
- }
- else if (act->type == ACT_SCENE) {
- bSceneActuator *sa = act->data;
- sa->camera= newlibadr(fd, ob->id.lib, sa->camera);
- sa->scene= newlibadr(fd, ob->id.lib, sa->scene);
- }
- else if (act->type == ACT_ACTION) {
- bActionActuator *aa = act->data;
- aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
- }
- else if (act->type == ACT_SHAPEACTION) {
- bActionActuator *aa = act->data;
- aa->act= newlibadr_us(fd, ob->id.lib, aa->act);
- }
- else if (act->type == ACT_PROPERTY) {
- bPropertyActuator *pa = act->data;
- pa->ob= newlibadr(fd, ob->id.lib, pa->ob);
- }
- else if (act->type == ACT_MESSAGE) {
- bMessageActuator *ma = act->data;
- ma->toObject= newlibadr(fd, ob->id.lib, ma->toObject);
- }
- else if (act->type == ACT_2DFILTER) {
- bTwoDFilterActuator *_2dfa = act->data;
- _2dfa->text= newlibadr(fd, ob->id.lib, _2dfa->text);
- }
- else if (act->type == ACT_PARENT) {
- bParentActuator *parenta = act->data;
- parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob);
- }
- else if (act->type == ACT_STATE) {
- /* bStateActuator *statea = act->data; */
- }
- else if (act->type == ACT_ARMATURE) {
- bArmatureActuator *arma= act->data;
- arma->target= newlibadr(fd, ob->id.lib, arma->target);
- arma->subtarget= newlibadr(fd, ob->id.lib, arma->subtarget);
- }
- else if (act->type == ACT_STEERING) {
- bSteeringActuator *steeringa = act->data;
- steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
- steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
- }
- else if (act->type == ACT_MOUSE) {
- /* bMouseActuator *moa= act->data; */
+ case ACT_EDIT_OBJECT:
+ {
+ bEditObjectActuator *eoa = act->data;
+ if (eoa == NULL) {
+ init_actuator(act);
+ }
+ else {
+ eoa->ob = newlibadr(fd, ob->id.lib, eoa->ob);
+ eoa->me = newlibadr(fd, ob->id.lib, eoa->me);
+ }
+ break;
+ }
+ case ACT_SCENE:
+ {
+ bSceneActuator *sa = act->data;
+ sa->camera = newlibadr(fd, ob->id.lib, sa->camera);
+ sa->scene = newlibadr(fd, ob->id.lib, sa->scene);
+ break;
+ }
+ case ACT_ACTION:
+ {
+ bActionActuator *aa = act->data;
+ aa->act = newlibadr_us(fd, ob->id.lib, aa->act);
+ break;
+ }
+ case ACT_SHAPEACTION:
+ {
+ bActionActuator *aa = act->data;
+ aa->act = newlibadr_us(fd, ob->id.lib, aa->act);
+ break;
+ }
+ case ACT_PROPERTY:
+ {
+ bPropertyActuator *pa = act->data;
+ pa->ob = newlibadr(fd, ob->id.lib, pa->ob);
+ break;
+ }
+ case ACT_MESSAGE:
+ {
+ bMessageActuator *ma = act->data;
+ ma->toObject = newlibadr(fd, ob->id.lib, ma->toObject);
+ break;
+ }
+ case ACT_2DFILTER:
+ {
+ bTwoDFilterActuator *_2dfa = act->data;
+ _2dfa->text = newlibadr(fd, ob->id.lib, _2dfa->text);
+ break;
+ }
+ case ACT_PARENT:
+ {
+ bParentActuator *parenta = act->data;
+ parenta->ob = newlibadr(fd, ob->id.lib, parenta->ob);
+ break;
+ }
+ case ACT_STATE:
+ /* bStateActuator *statea = act->data; */
+ break;
+ case ACT_ARMATURE:
+ {
+ bArmatureActuator *arma= act->data;
+ arma->target = newlibadr(fd, ob->id.lib, arma->target);
+ arma->subtarget = newlibadr(fd, ob->id.lib, arma->subtarget);
+ break;
+ }
+ case ACT_STEERING:
+ {
+ bSteeringActuator *steeringa = act->data;
+ steeringa->target = newlibadr(fd, ob->id.lib, steeringa->target);
+ steeringa->navmesh = newlibadr(fd, ob->id.lib, steeringa->navmesh);
+ break;
+ }
+ case ACT_MOUSE:
+ /* bMouseActuator *moa = act->data; */
+ break;
}
}
@@ -5327,6 +5324,37 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
MeshSeqCacheModifierData *msmcd = (MeshSeqCacheModifierData *)md;
msmcd->reader = NULL;
}
+ else if (md->type == eModifierType_SurfaceDeform) {
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ smd->verts = newdataadr(fd, smd->verts);
+
+ if (smd->verts) {
+ for (int i = 0; i < smd->numverts; i++) {
+ smd->verts[i].binds = newdataadr(fd, smd->verts[i].binds);
+
+ if (smd->verts[i].binds) {
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ smd->verts[i].binds[j].vert_inds = newdataadr(fd, smd->verts[i].binds[j].vert_inds);
+ smd->verts[i].binds[j].vert_weights = newdataadr(fd, smd->verts[i].binds[j].vert_weights);
+
+ if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) {
+ if (smd->verts[i].binds[j].vert_inds)
+ BLI_endian_switch_uint32_array(smd->verts[i].binds[j].vert_inds, smd->verts[i].binds[j].numverts);
+
+ if (smd->verts[i].binds[j].vert_weights) {
+ if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
+ smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI)
+ BLI_endian_switch_float_array(smd->verts[i].binds[j].vert_weights, 3);
+ else
+ BLI_endian_switch_float_array(smd->verts[i].binds[j].vert_weights, smd->verts[i].binds[j].numverts);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
@@ -5558,8 +5586,8 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->bb = NULL;
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
- ob->collection_settings = NULL;
BLI_listbase_clear(&ob->gpulamp);
+ BLI_listbase_clear(&ob->drawdata);
link_list(fd, &ob->pc_ids);
/* Runtime curve data */
@@ -5576,6 +5604,8 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->currentlod = ob->lodlevels.first;
ob->preview = direct_link_preview_image(fd, ob->preview);
+
+ ob->base_collection_properties = NULL;
}
/* ************ READ SCENE ***************** */
@@ -5659,20 +5689,12 @@ static void lib_link_scene_collection(FileData *fd, Library *lib, SceneCollectio
static void lib_link_scene(FileData *fd, Main *main)
{
- Scene *sce;
- BaseLegacy *base_legacy, *base_legacy_next;
- Sequence *seq;
- SceneLayer *sl;
- SceneRenderLayer *srl;
- FreestyleModuleConfig *fmc;
- FreestyleLineSet *fls;
-
#ifdef USE_SETSCENE_CHECK
bool need_check_set = false;
int totscene = 0;
#endif
- for (sce = main->scene.first; sce; sce = sce->id.next) {
+ for (Scene *sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.tag & LIB_TAG_NEED_LINK) {
/* Link ID Properties -- and copy this comment EXACTLY for easy finding
* of library blocks that implement this.*/
@@ -5712,7 +5734,7 @@ static void lib_link_scene(FileData *fd, Main *main)
sce->toolsettings->particle.shape_object = newlibadr(fd, sce->id.lib, sce->toolsettings->particle.shape_object);
- for (base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
+ for (BaseLegacy *base_legacy_next, *base_legacy = sce->base.first; base_legacy; base_legacy = base_legacy_next) {
base_legacy_next = base_legacy->next;
base_legacy->object = newlibadr_us(fd, sce->id.lib, base_legacy->object);
@@ -5726,6 +5748,7 @@ static void lib_link_scene(FileData *fd, Main *main)
}
}
+ Sequence *seq;
SEQ_BEGIN (sce->ed, seq)
{
if (seq->ipo) seq->ipo = newlibadr_us(fd, sce->id.lib, seq->ipo); // XXX deprecated - old animation system
@@ -5791,13 +5814,13 @@ static void lib_link_scene(FileData *fd, Main *main)
composite_patch(sce->nodetree, sce);
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
srl->mat_override = newlibadr_us(fd, sce->id.lib, srl->mat_override);
srl->light_override = newlibadr_us(fd, sce->id.lib, srl->light_override);
- for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
fmc->script = newlibadr(fd, sce->id.lib, fmc->script);
}
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
fls->linestyle = newlibadr_us(fd, sce->id.lib, fls->linestyle);
fls->group = newlibadr_us(fd, sce->id.lib, fls->group);
}
@@ -5810,10 +5833,14 @@ static void lib_link_scene(FileData *fd, Main *main)
lib_link_scene_collection(fd, sce->id.lib, sce->collection);
- for (sl = sce->render_layers.first; sl; sl = sl->next) {
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+ /* tag scene layer to update for collection tree evaluation */
+ sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
for (Base *base = sl->object_bases.first; base; base = base->next) {
/* we only bump the use count for the collection objects */
base->object = newlibadr(fd, sce->id.lib, base->object);
+ base->flag |= BASE_DIRTY_ENGINE_SETTINGS;
+ base->collection_properties = NULL;
}
}
@@ -5840,7 +5867,7 @@ static void lib_link_scene(FileData *fd, Main *main)
#ifdef USE_SETSCENE_CHECK
if (need_check_set) {
- for (sce = main->scene.first; sce; sce = sce->id.next) {
+ for (Scene *sce = main->scene.first; sce; sce = sce->id.next) {
if (sce->id.tag & LIB_TAG_NEED_LINK) {
sce->id.tag &= ~LIB_TAG_NEED_LINK;
if (!scene_validate_setscene__liblink(sce, totscene)) {
@@ -5931,14 +5958,6 @@ static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
}
}
-static void direct_link_engine_settings(FileData *fd, ListBase *lb)
-{
- link_list(fd, lb);
- for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
- link_list(fd, &ces->properties);
- }
-}
-
static void direct_link_layer_collections(FileData *fd, ListBase *lb)
{
link_list(fd, lb);
@@ -5953,7 +5972,11 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb)
link_list(fd, &lc->overrides);
- direct_link_engine_settings(fd, &lc->engine_settings);
+ if (lc->properties) {
+ lc->properties = newdataadr(fd, lc->properties);
+ IDP_DirectLinkGroup_OrFree(&lc->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+ }
+ lc->properties_evaluated = NULL;
direct_link_layer_collections(fd, &lc->layer_collections);
}
@@ -5967,7 +5990,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
RigidBodyWorld *rbw;
SceneLayer *sl;
SceneRenderLayer *srl;
- RenderEngineSettings *res;
sce->theDag = NULL;
sce->depsgraph = NULL;
@@ -6004,6 +6026,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
+ sce->toolsettings->particle.scene_layer = NULL;
sce->toolsettings->particle.object = NULL;
sce->toolsettings->gp_sculpt.paintcursor = NULL;
@@ -6231,10 +6254,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_layer_collections(fd, &sl->layer_collections);
}
- link_list(fd, &sce->engines_settings);
- for (res = sce->engines_settings.first; res; res = res->next) {
- res->data = newdataadr(fd, res->data);
- }
+ sce->collection_properties = newdataadr(fd, sce->collection_properties);
+ IDP_DirectLinkGroup_OrFree(&sce->collection_properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
/* ************ READ WM ***************** */
@@ -6309,8 +6330,10 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
for (wm = main->wm.first; wm; wm = wm->id.next) {
if (wm->id.tag & LIB_TAG_NEED_LINK) {
- for (win = wm->windows.first; win; win = win->next)
+ /* Note: WM IDProperties are never written to file, hence no need to read/link them here. */
+ for (win = wm->windows.first; win; win = win->next) {
win->screen = newlibadr(fd, NULL, win->screen);
+ }
wm->id.tag &= ~LIB_TAG_NEED_LINK;
}
@@ -6322,13 +6345,12 @@ static void lib_link_windowmanager(FileData *fd, Main *main)
/* relink's grease pencil data's refs */
static void lib_link_gpencil(FileData *fd, Main *main)
{
- bGPdata *gpd;
-
- for (gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
+ for (bGPdata *gpd = main->gpencil.first; gpd; gpd = gpd->id.next) {
if (gpd->id.tag & LIB_TAG_NEED_LINK) {
- gpd->id.tag &= ~LIB_TAG_NEED_LINK;
-
+ IDP_LibLinkProperty(gpd->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &gpd->id, gpd->adt);
+
+ gpd->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -6390,12 +6412,11 @@ static void direct_link_gpencil(FileData *fd, bGPdata *gpd)
* check lib pointers in call below */
static void lib_link_screen(FileData *fd, Main *main)
{
- bScreen *sc;
- ScrArea *sa;
-
- for (sc = main->screen.first; sc; sc = sc->id.next) {
+ for (bScreen *sc = main->screen.first; sc; sc = sc->id.next) {
if (sc->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(sc->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
id_us_ensure_real(&sc->id);
+
sc->scene = newlibadr(fd, sc->id.lib, sc->scene);
/* this should not happen, but apparently it does somehow. Until we figure out the cause,
@@ -6406,181 +6427,204 @@ static void lib_link_screen(FileData *fd, Main *main)
sc->animtimer = NULL; /* saved in rare cases */
sc->scrubbing = false;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
-
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
sa->full = newlibadr(fd, sc->id.lib, sa->full);
- for (sl = sa->spacedata.first; sl; sl= sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D*) sl;
- BGpic *bgpic = NULL;
-
- v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
- v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
-
- /* should be do_versions but not easy adding into the listbase */
- if (v3d->bgpic) {
- v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic);
- BLI_addtail(&v3d->bgpicbase, bgpic);
- v3d->bgpic = NULL;
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl= sl->next) {
+ switch (sl->spacetype) {
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = (View3D*) sl;
+ BGpic *bgpic = NULL;
+
+ v3d->camera= newlibadr(fd, sc->id.lib, v3d->camera);
+ v3d->ob_centre= newlibadr(fd, sc->id.lib, v3d->ob_centre);
+
+ /* should be do_versions but not easy adding into the listbase */
+ if (v3d->bgpic) {
+ v3d->bgpic = newlibadr(fd, sc->id.lib, v3d->bgpic);
+ BLI_addtail(&v3d->bgpicbase, bgpic);
+ v3d->bgpic = NULL;
+ }
+
+ for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima);
+ bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip);
+ }
+ if (v3d->localvd) {
+ v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera);
+ }
+ break;
}
-
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- bgpic->ima = newlibadr_us(fd, sc->id.lib, bgpic->ima);
- bgpic->clip = newlibadr_us(fd, sc->id.lib, bgpic->clip);
+ case SPACE_IPO:
+ {
+ SpaceIpo *sipo = (SpaceIpo *)sl;
+ bDopeSheet *ads = sipo->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+ break;
}
- if (v3d->localvd) {
- v3d->localvd->camera = newlibadr(fd, sc->id.lib, v3d->localvd->camera);
+ case SPACE_BUTS:
+ {
+ SpaceButs *sbuts = (SpaceButs *)sl;
+ sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
+ if (sbuts->pinid == NULL) {
+ sbuts->flag &= ~SB_PIN_CONTEXT;
+ }
+ break;
}
- }
- else if (sl->spacetype == SPACE_IPO) {
- SpaceIpo *sipo = (SpaceIpo *)sl;
- bDopeSheet *ads = sipo->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ case SPACE_FILE:
+ break;
+ case SPACE_ACTION:
+ {
+ SpaceAction *saction = (SpaceAction *)sl;
+ bDopeSheet *ads = &saction->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+
+ saction->action = newlibadr(fd, sc->id.lib, saction->action);
+ break;
}
- }
- else if (sl->spacetype == SPACE_BUTS) {
- SpaceButs *sbuts = (SpaceButs *)sl;
- sbuts->pinid = newlibadr(fd, sc->id.lib, sbuts->pinid);
- if (sbuts->pinid == NULL) {
- sbuts->flag &= ~SB_PIN_CONTEXT;
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = (SpaceImage *)sl;
+
+ sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image);
+ sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask);
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd);
+ break;
}
- }
- else if (sl->spacetype == SPACE_FILE) {
- ;
- }
- else if (sl->spacetype == SPACE_ACTION) {
- SpaceAction *saction = (SpaceAction *)sl;
- bDopeSheet *ads = &saction->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+
+ /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
+ * so fingers crossed this works fine!
+ */
+ sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
+ break;
}
-
- saction->action = newlibadr(fd, sc->id.lib, saction->action);
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
-
- sima->image = newlibadr_real_us(fd, sc->id.lib, sima->image);
- sima->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sima->mask_info.mask);
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- sima->gpd = newlibadr_us(fd, sc->id.lib, sima->gpd);
- }
- else if (sl->spacetype == SPACE_SEQ) {
- SpaceSeq *sseq = (SpaceSeq *)sl;
-
- /* NOTE: pre-2.5, this was local data not lib data, but now we need this as lib data
- * so fingers crossed this works fine!
- */
- sseq->gpd = newlibadr_us(fd, sc->id.lib, sseq->gpd);
+ case SPACE_NLA:
+ {
+ SpaceNla *snla= (SpaceNla *)sl;
+ bDopeSheet *ads= snla->ads;
+
+ if (ads) {
+ ads->source = newlibadr(fd, sc->id.lib, ads->source);
+ ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ }
+ break;
+ }
+ case SPACE_TEXT:
+ {
+ SpaceText *st= (SpaceText *)sl;
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla= (SpaceNla *)sl;
- bDopeSheet *ads= snla->ads;
-
- if (ads) {
- ads->source = newlibadr(fd, sc->id.lib, ads->source);
- ads->filter_grp = newlibadr(fd, sc->id.lib, ads->filter_grp);
+ st->text= newlibadr(fd, sc->id.lib, st->text);
+ break;
}
- }
- else if (sl->spacetype == SPACE_TEXT) {
- SpaceText *st= (SpaceText *)sl;
-
- st->text= newlibadr(fd, sc->id.lib, st->text);
- }
- else if (sl->spacetype == SPACE_SCRIPT) {
- SpaceScript *scpt = (SpaceScript *)sl;
- /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
- if (scpt->script) {
- scpt->script = newlibadr(fd, sc->id.lib, scpt->script);
+ case SPACE_SCRIPT:
+ {
+ SpaceScript *scpt = (SpaceScript *)sl;
+ /*scpt->script = NULL; - 2.45 set to null, better re-run the script */
if (scpt->script) {
- SCRIPT_SET_NULL(scpt->script);
+ scpt->script = newlibadr(fd, sc->id.lib, scpt->script);
+ if (scpt->script) {
+ SCRIPT_SET_NULL(scpt->script);
+ }
}
+ break;
}
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so= (SpaceOops *)sl;
- so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
-
- if (so->treestore) {
- TreeStoreElem *tselem;
- BLI_mempool_iter iter;
+ case SPACE_OUTLINER:
+ {
+ SpaceOops *so= (SpaceOops *)sl;
+ so->search_tse.id = newlibadr(fd, NULL, so->search_tse.id);
+
+ if (so->treestore) {
+ TreeStoreElem *tselem;
+ BLI_mempool_iter iter;
+
+ BLI_mempool_iternew(so->treestore, &iter);
+ while ((tselem = BLI_mempool_iterstep(&iter))) {
+ tselem->id = newlibadr(fd, NULL, tselem->id);
+ }
+ if (so->treehash) {
+ /* rebuild hash table, because it depends on ids too */
+ so->storeflag |= SO_TREESTORE_REBUILD;
+ }
+ }
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path, *path_next;
+ bNodeTree *ntree;
+
+ /* node tree can be stored locally in id too, link this first */
+ snode->id = newlibadr(fd, sc->id.lib, snode->id);
+ snode->from = newlibadr(fd, sc->id.lib, snode->from);
+
+ ntree = snode->id ? ntreeFromID(snode->id) : NULL;
+ snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree);
+
+ for (path = snode->treepath.first; path; path = path->next) {
+ if (path == snode->treepath.first) {
+ /* first nodetree in path is same as snode->nodetree */
+ path->nodetree = snode->nodetree;
+ }
+ else
+ path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree);
- BLI_mempool_iternew(so->treestore, &iter);
- while ((tselem = BLI_mempool_iterstep(&iter))) {
- tselem->id = newlibadr(fd, NULL, tselem->id);
+ if (!path->nodetree)
+ break;
}
- if (so->treehash) {
- /* rebuild hash table, because it depends on ids too */
- so->storeflag |= SO_TREESTORE_REBUILD;
+
+ /* remaining path entries are invalid, remove */
+ for (; path; path = path_next) {
+ path_next = path->next;
+
+ BLI_remlink(&snode->treepath, path);
+ MEM_freeN(path);
}
- }
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path, *path_next;
- bNodeTree *ntree;
-
- /* node tree can be stored locally in id too, link this first */
- snode->id = newlibadr(fd, sc->id.lib, snode->id);
- snode->from = newlibadr(fd, sc->id.lib, snode->from);
-
- ntree = snode->id ? ntreeFromID(snode->id) : NULL;
- snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree);
-
- for (path = snode->treepath.first; path; path = path->next) {
- if (path == snode->treepath.first) {
- /* first nodetree in path is same as snode->nodetree */
- path->nodetree = snode->nodetree;
+
+ /* edittree is just the last in the path,
+ * set this directly since the path may have been shortened above */
+ if (snode->treepath.last) {
+ path = snode->treepath.last;
+ snode->edittree = path->nodetree;
}
- else
- path->nodetree = newlibadr_us(fd, sc->id.lib, path->nodetree);
-
- if (!path->nodetree)
- break;
+ else {
+ snode->edittree = NULL;
+ }
+ break;
}
-
- /* remaining path entries are invalid, remove */
- for (; path; path = path_next) {
- path_next = path->next;
-
- BLI_remlink(&snode->treepath, path);
- MEM_freeN(path);
+ case SPACE_CLIP:
+ {
+ SpaceClip *sclip = (SpaceClip *)sl;
+
+ sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip);
+ sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask);
+ break;
}
-
- /* edittree is just the last in the path,
- * set this directly since the path may have been shortened above */
- if (snode->treepath.last) {
- path = snode->treepath.last;
- snode->edittree = path->nodetree;
+ case SPACE_LOGIC:
+ {
+ SpaceLogic *slogic = (SpaceLogic *)sl;
+
+ slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
+ break;
}
- else
- snode->edittree = NULL;
- }
- else if (sl->spacetype == SPACE_CLIP) {
- SpaceClip *sclip = (SpaceClip *)sl;
-
- sclip->clip = newlibadr_real_us(fd, sc->id.lib, sclip->clip);
- sclip->mask_info.mask = newlibadr_real_us(fd, sc->id.lib, sclip->mask_info.mask);
- }
- else if (sl->spacetype == SPACE_LOGIC) {
- SpaceLogic *slogic = (SpaceLogic *)sl;
-
- slogic->gpd = newlibadr_us(fd, sc->id.lib, slogic->gpd);
- }
- else if (sl->spacetype == SPACE_COLLECTIONS) {
- SpaceCollections *slayer = (SpaceCollections *)sl;
- slayer->flag |= SC_COLLECTION_DATA_REFRESH;
+ default:
+ break;
}
}
}
@@ -6967,10 +7011,6 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
slogic->gpd = restore_pointer_by_name(id_map, (ID *)slogic->gpd, USER_REAL);
}
- else if (sl->spacetype == SPACE_COLLECTIONS) {
- SpaceCollections *slayer = (SpaceCollections *)sl;
- slayer->flag |= SC_COLLECTION_DATA_REFRESH;
- }
}
}
}
@@ -7365,10 +7405,6 @@ static bool direct_link_screen(FileData *fd, bScreen *sc)
sclip->scopes.track_preview = NULL;
sclip->scopes.ok = 0;
}
- else if (sl->spacetype == SPACE_COLLECTIONS) {
- SpaceCollections *slayer = (SpaceCollections *)sl;
- slayer->flag |= SC_COLLECTION_DATA_REFRESH;
- }
}
BLI_listbase_clear(&sa->actionzones);
@@ -7466,13 +7502,13 @@ static void fix_relpaths_library(const char *basepath, Main *main)
static void lib_link_speaker(FileData *fd, Main *main)
{
- Speaker *spk;
-
- for (spk = main->speaker.first; spk; spk = spk->id.next) {
+ for (Speaker *spk = main->speaker.first; spk; spk = spk->id.next) {
if (spk->id.tag & LIB_TAG_NEED_LINK) {
+ IDP_LibLinkProperty(spk->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &spk->id, spk->adt);
spk->sound = newlibadr_us(fd, spk->id.lib, spk->sound);
+
spk->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
@@ -7522,14 +7558,15 @@ static void direct_link_sound(FileData *fd, bSound *sound)
static void lib_link_sound(FileData *fd, Main *main)
{
- bSound *sound;
-
- for (sound = main->sound.first; sound; sound = sound->id.next) {
+ for (bSound *sound = main->sound.first; sound; sound = sound->id.next) {
if (sound->id.tag & LIB_TAG_NEED_LINK) {
- sound->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(sound->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
+
sound->ipo = newlibadr_us(fd, sound->id.lib, sound->ipo); // XXX deprecated - old animation system
BKE_sound_load(main, sound);
+
+ sound->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -7544,17 +7581,13 @@ static void direct_link_group(FileData *fd, Group *group)
static void lib_link_group(FileData *fd, Main *main)
{
- Group *group;
- GroupObject *go;
- bool add_us;
-
- for (group = main->group.first; group; group = group->id.next) {
+ for (Group *group = main->group.first; group; group = group->id.next) {
if (group->id.tag & LIB_TAG_NEED_LINK) {
- group->id.tag &= ~LIB_TAG_NEED_LINK;
+ IDP_LibLinkProperty(group->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
- add_us = false;
+ bool add_us = false;
- for (go = group->gobject.first; go; go = go->next) {
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
go->ob = newlibadr_real_us(fd, group->id.lib, go->ob);
if (go->ob) {
go->ob->flag |= OB_FROMGROUP;
@@ -7566,6 +7599,8 @@ static void lib_link_group(FileData *fd, Main *main)
id_us_ensure_real(&group->id);
}
BKE_group_object_unlink(group, NULL); /* removes NULL entries */
+
+ group->id.tag &= ~LIB_TAG_NEED_LINK;
}
}
}
@@ -7670,13 +7705,11 @@ static void lib_link_moviePlaneTracks(FileData *fd, MovieClip *clip, ListBase *t
static void lib_link_movieclip(FileData *fd, Main *main)
{
- MovieClip *clip;
-
- for (clip = main->movieclip.first; clip; clip = clip->id.next) {
+ for (MovieClip *clip = main->movieclip.first; clip; clip = clip->id.next) {
if (clip->id.tag & LIB_TAG_NEED_LINK) {
MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ IDP_LibLinkProperty(clip->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &clip->id, clip->adt);
clip->gpd = newlibadr_us(fd, clip->id.lib, clip->gpd);
@@ -7684,7 +7717,7 @@ static void lib_link_movieclip(FileData *fd, Main *main)
lib_link_movieTracks(fd, clip, &tracking->tracks);
lib_link_moviePlaneTracks(fd, clip, &tracking->plane_tracks);
- for (object = tracking->objects.first; object; object = object->next) {
+ for (MovieTrackingObject *object = tracking->objects.first; object; object = object->next) {
lib_link_movieTracks(fd, clip, &object->tracks);
lib_link_moviePlaneTracks(fd, clip, &object->plane_tracks);
}
@@ -7761,16 +7794,12 @@ static void lib_link_mask_parent(FileData *fd, Mask *mask, MaskParent *parent)
static void lib_link_mask(FileData *fd, Main *main)
{
- Mask *mask;
-
- mask = main->mask.first;
- while (mask) {
+ for (Mask *mask = main->mask.first; mask; mask = mask->id.next) {
if (mask->id.tag & LIB_TAG_NEED_LINK) {
- MaskLayer *masklay;
-
+ IDP_LibLinkProperty(mask->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &mask->id, mask->adt);
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ for (MaskLayer *masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
MaskSpline *spline;
spline = masklay->splines.first;
@@ -7791,7 +7820,6 @@ static void lib_link_mask(FileData *fd, Main *main)
mask->id.tag &= ~LIB_TAG_NEED_LINK;
}
- mask = mask->id.next;
}
}
@@ -7799,18 +7827,13 @@ static void lib_link_mask(FileData *fd, Main *main)
static void lib_link_linestyle(FileData *fd, Main *main)
{
- FreestyleLineStyle *linestyle;
- LineStyleModifier *m;
- MTex *mtex;
- int a;
-
- linestyle = main->linestyle.first;
- while (linestyle) {
+ for (FreestyleLineStyle *linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) {
if (linestyle->id.tag & LIB_TAG_NEED_LINK) {
- linestyle->id.tag &= ~LIB_TAG_NEED_LINK;
+ LineStyleModifier *m;
IDP_LibLinkProperty(linestyle->id.properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
lib_link_animdata(fd, &linestyle->id, linestyle->adt);
+
for (m = linestyle->color_modifiers.first; m; m = m->next) {
switch (m->type) {
case LS_MODIFIER_DISTANCE_FROM_OBJECT:
@@ -7841,8 +7864,8 @@ static void lib_link_linestyle(FileData *fd, Main *main)
break;
}
}
- for (a=0; a < MAX_MTEX; a++) {
- mtex = linestyle->mtex[a];
+ for (int a = 0; a < MAX_MTEX; a++) {
+ MTex *mtex = linestyle->mtex[a];
if (mtex) {
mtex->tex = newlibadr_us(fd, linestyle->id.lib, mtex->tex);
mtex->object = newlibadr(fd, linestyle->id.lib, mtex->object);
@@ -7852,8 +7875,9 @@ static void lib_link_linestyle(FileData *fd, Main *main)
lib_link_ntree(fd, &linestyle->id, linestyle->nodetree);
linestyle->nodetree->id.lib = linestyle->id.lib;
}
+
+ linestyle->id.tag &= ~LIB_TAG_NEED_LINK;
}
- linestyle = linestyle->id.next;
}
}
@@ -8509,6 +8533,7 @@ static void do_versions_after_linking(Main *main)
{
// printf("%s for %s (%s), %d.%d\n", __func__, main->curlib ? main->curlib->name : main->name,
// main->curlib ? "LIB" : "MAIN", main->versionfile, main->subversionfile);
+
do_versions_after_linking_270(main);
do_versions_after_linking_280(main);
}
@@ -8525,12 +8550,13 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_screen(fd, main);
lib_link_scene(fd, main);
lib_link_object(fd, main);
+ lib_link_mesh(fd, main);
lib_link_curve(fd, main);
lib_link_mball(fd, main);
lib_link_material(fd, main);
lib_link_texture(fd, main);
lib_link_image(fd, main);
- lib_link_ipo(fd, main); // XXX deprecated... still needs to be maintained for version patches still
+ lib_link_ipo(fd, main); /* XXX deprecated... still needs to be maintained for version patches still */
lib_link_key(fd, main);
lib_link_world(fd, main);
lib_link_lamp(fd, main);
@@ -8543,7 +8569,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_armature(fd, main);
lib_link_action(fd, main);
lib_link_vfont(fd, main);
- lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
+ lib_link_nodetree(fd, main); /* has to be done after scene/materials, this will verify group nodes */
lib_link_brush(fd, main);
lib_link_palette(fd, main);
lib_link_paint_curve(fd, main);
@@ -8554,9 +8580,7 @@ static void lib_link_all(FileData *fd, Main *main)
lib_link_gpencil(fd, main);
lib_link_cachefiles(fd, main);
- lib_link_mesh(fd, main); /* as last: tpage images with users at zero */
-
- lib_link_library(fd, main); /* only init users */
+ lib_link_library(fd, main); /* only init users */
}
static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi)
@@ -8680,7 +8704,12 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
bhead = read_global(bfd, fd, bhead);
break;
case USER:
- bhead = read_userdef(bfd, fd, bhead);
+ if (fd->skip_flags & BLO_READ_SKIP_USERDEF) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_userdef(bfd, fd, bhead);
+ }
break;
case ENDB:
bhead = NULL;
@@ -8689,15 +8718,24 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
case ID_ID:
/* Always adds to the most recently loaded ID_LI block, see direct_link_library.
* This is part of the file format definition. */
- bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL);
+ if (fd->skip_flags & BLO_READ_SKIP_DATA) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_libblock(fd, mainlist.last, bhead, LIB_TAG_READ | LIB_TAG_EXTERN, NULL);
+ }
break;
-
/* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
case ID_SCRN:
bhead->code = ID_SCR;
/* deliberate pass on to default */
default:
- bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL);
+ if (fd->skip_flags & BLO_READ_SKIP_DATA) {
+ bhead = blo_nextbhead(fd, bhead);
+ }
+ else {
+ bhead = read_libblock(fd, bfd->main, bhead, LIB_TAG_LOCAL, NULL);
+ }
}
}
@@ -9485,7 +9523,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob)
expand_doit(fd, mainvar, ob->proxy);
if (ob->proxy_group)
expand_doit(fd, mainvar, ob->proxy_group);
-
+
for (psys = ob->particlesystem.first; psys; psys = psys->next)
expand_doit(fd, mainvar, psys->part);
@@ -10526,6 +10564,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist)
else {
mainptr->curlib->filedata = NULL;
mainptr->curlib->id.tag |= LIB_TAG_MISSING;
+ /* Set lib version to current main one... Makes assert later happy. */
+ mainptr->versionfile = mainptr->curlib->versionfile = mainl->versionfile;
+ mainptr->subversionfile = mainptr->curlib->subversionfile = mainl->subversionfile;
}
if (fd == NULL) {
diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h
index 50cdeca16b5..299c66f2bbb 100644
--- a/source/blender/blenloader/intern/readfile.h
+++ b/source/blender/blenloader/intern/readfile.h
@@ -83,6 +83,8 @@ typedef struct FileData {
int id_name_offs; /* used to retrieve ID names from (bhead+1) */
int globalf, fileflags; /* for do_versions patching */
+ eBLOReadSkip skip_flags; /* skip some data-blocks */
+
struct OldNewMap *datamap;
struct OldNewMap *globmap;
struct OldNewMap *libmap;
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index 5df20d443a6..c03fcfb954c 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1575,6 +1575,40 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
}
+ /* Fix for T50736, Glare comp node using same var for two different things. */
+ if (!DNA_struct_elem_find(fd->filesdna, "NodeGlare", "char", "star_45")) {
+ FOREACH_NODETREE(main, ntree, id) {
+ if (ntree->type == NTREE_COMPOSIT) {
+ ntreeSetTypes(NULL, ntree);
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_GLARE) {
+ NodeGlare *ndg = node->storage;
+ switch (ndg->type) {
+ case 2: /* Grrrr! magic numbers :( */
+ ndg->streaks = ndg->angle;
+ break;
+ case 0:
+ ndg->star_45 = ndg->angle != 0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ } FOREACH_NODETREE_END
+ }
+
+ if (!DNA_struct_elem_find(fd->filesdna, "SurfaceDeformModifierData", "float", "mat[4][4]")) {
+ for (Object *ob = main->object.first; ob; ob = ob->id.next) {
+ for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_SurfaceDeform) {
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ unit_m4(smd->mat);
+ }
+ }
+ }
+ }
}
{
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 432d8be0a6d..58724459a45 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -32,14 +32,18 @@
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_genfile.h"
+#include "BKE_blender.h"
#include "BKE_collection.h"
+#include "BKE_idprop.h"
#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BLI_listbase.h"
+#include "BLI_mempool.h"
#include "BLI_string.h"
#include "BLO_readfile.h"
@@ -50,6 +54,9 @@
void do_versions_after_linking_280(Main *main)
{
if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ char version[48];
+ BKE_blender_version_string(version, sizeof(version), main->versionfile, main->subversionfile, false, false);
+
for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
/* since we don't have access to FileData we check the (always valid) first render layer instead */
if (scene->render_layers.first == NULL) {
@@ -63,7 +70,7 @@ void do_versions_after_linking_280(Main *main)
for (int i = 0; i < 20; i++) {
char name[MAX_NAME];
- BLI_snprintf(name, sizeof(collections[i]->name), "%d", i + 1);
+ BLI_snprintf(name, sizeof(collections[i]->name), "Collection %d [converted from %s]", i + 1, version);
collections[i] = BKE_collection_add(scene, sc_master, name);
is_visible[i] = (scene->lay & (1 << i));
@@ -121,7 +128,7 @@ void do_versions_after_linking_280(Main *main)
}
}
- SceneLayer *sl = BKE_scene_layer_add(scene, "Render Layer");
+ SceneLayer *sl = BKE_scene_layer_add(scene, "Viewport");
/* In this particular case we can safely assume the data struct */
LayerCollection *lc = ((LayerCollection *)sl->layer_collections.first)->layer_collections.first;
@@ -132,9 +139,6 @@ void do_versions_after_linking_280(Main *main)
lc = lc->next;
}
- /* but we still need to make the flags synced */
- BKE_scene_layer_base_flag_recalculate(sl);
-
/* convert active base */
if (scene->basact) {
sl->basact = BKE_scene_layer_base_find(sl, scene->basact->object);
@@ -151,6 +155,9 @@ void do_versions_after_linking_280(Main *main)
else {
ob_base->flag &= ~BASE_SELECTED;
}
+
+ /* keep lay around for forward compatibility (open those files in 2.79) */
+ ob_base->lay = base->lay;
}
/* TODO: copy scene render data to layer */
@@ -162,6 +169,11 @@ void do_versions_after_linking_280(Main *main)
}
}
+ /* Fallback name if only one layer was found in the original file */
+ if (BLI_listbase_count_ex(&sc_master->scene_collections, 2) == 1) {
+ BKE_collection_rename(scene, sc_master->scene_collections.first, "Default Collection");
+ }
+
/* remove bases once and for all */
for (Base *base = scene->base.first; base; base = base->next) {
id_us_min(&base->object->id);
@@ -170,6 +182,57 @@ void do_versions_after_linking_280(Main *main)
scene->basact = NULL;
}
}
+
+ for (bScreen *screen = main->screen.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOops *soutliner = (SpaceOops *)sl;
+ SceneLayer *layer = BKE_scene_layer_context_active(screen->scene);
+
+ soutliner->outlinevis = SO_ACT_LAYER;
+
+ if (BLI_listbase_count_ex(&layer->layer_collections, 2) == 1) {
+ /* Create a tree store element for the collection. This is normally
+ * done in check_persistent (outliner_tree.c), but we need to access
+ * it here :/ (expand element if it's the only one) */
+ TreeStoreElem *tselem = BLI_mempool_calloc(soutliner->treestore);
+ tselem->type = TSE_LAYER_COLLECTION;
+ tselem->id = layer->layer_collections.first;
+ tselem->nr = tselem->used = 0;
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (!MAIN_VERSION_ATLEAST(main, 280, 0)) {
+ IDPropertyTemplate val = {0};
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ scene->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(scene->collection_properties);
+ }
+ }
+}
+
+static void do_version_layer_collections_idproperties(ListBase *lb)
+{
+ IDPropertyTemplate val = {0};
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(lc->properties);
+
+ /* No overrides at first */
+ for (IDProperty *prop = lc->properties->data.group.first; prop; prop = prop->next) {
+ while (prop->data.group.first) {
+ IDP_FreeFromGroup(prop, prop->data.group.first);
+ }
+ }
+
+ /* Do it recursively */
+ do_version_layer_collections_idproperties(&lc->layer_collections);
}
}
@@ -183,5 +246,15 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *main)
BLI_strncpy(scene->collection->name, "Master Collection", sizeof(scene->collection->name));
}
}
+
+ if (DNA_struct_elem_find(fd->filesdna, "LayerCollection", "ListBase", "engine_settings") &&
+ !DNA_struct_elem_find(fd->filesdna, "LayerCollection", "IDProperty", "properties"))
+ {
+ for (Scene *scene = main->scene.first; scene; scene = scene->id.next) {
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ do_version_layer_collections_idproperties(&sl->layer_collections);
+ }
+ }
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 99d9e140481..e34f12b1cf9 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -68,6 +68,18 @@ void BLO_update_defaults_userpref_blend(void)
* but take care since some hardware has driver bugs here (T46962).
* Further hardware workarounds should be made in gpu_extensions.c */
U.glalphaclip = (1.0f / 255);
+
+ /* default so DPI is detected automatically */
+ U.dpi = 0;
+ U.ui_scale = 1.0f;
+
+#ifdef WITH_PYTHON_SECURITY
+ /* use alternative setting for security nuts
+ * otherwise we'd need to patch the binary blob - startup.blend.c */
+ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
+#else
+ U.flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE;
+#endif
}
/**
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 16d73557bb0..6550ad9a2fd 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -78,7 +78,7 @@
* - write #TEST (#RenderInfo struct. 128x128 blend file preview is optional).
* - write #GLOB (#FileGlobal struct) (some global vars).
* - write #DNA1 (#SDNA struct)
- * - write #USER (#UserDef struct) if filename is ``~/X.XX/config/startup.blend``.
+ * - write #USER (#UserDef struct) if filename is ``~/.config/blender/X.XX/config/startup.blend``.
*/
@@ -798,26 +798,22 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
}
}
-static void write_actions(WriteData *wd, ListBase *idbase)
+static void write_action(WriteData *wd, bAction *act)
{
- for (bAction *act = idbase->first; act; act = act->id.next) {
- if (act->id.us > 0 || wd->current) {
- writestruct(wd, ID_AC, bAction, 1, act);
- write_iddata(wd, &act->id);
+ if (act->id.us > 0 || wd->current) {
+ writestruct(wd, ID_AC, bAction, 1, act);
+ write_iddata(wd, &act->id);
- write_fcurves(wd, &act->curves);
+ write_fcurves(wd, &act->curves);
- for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
- writestruct(wd, DATA, bActionGroup, 1, grp);
- }
+ for (bActionGroup *grp = act->groups.first; grp; grp = grp->next) {
+ writestruct(wd, DATA, bActionGroup, 1, grp);
+ }
- for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
- }
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
+ writestruct(wd, DATA, TimeMarker, 1, marker);
}
}
-
- mywrite_flush(wd);
}
static void write_keyingsets(WriteData *wd, ListBase *list)
@@ -966,7 +962,7 @@ static void write_node_socket_interface(WriteData *wd, bNodeTree *UNUSED(ntree),
}
}
/* this is only direct data, tree itself should have been written */
-static void write_nodetree(WriteData *wd, bNodeTree *ntree)
+static void write_nodetree_nolib(WriteData *wd, bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
@@ -1027,6 +1023,25 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
/* pass */
}
+ else if ((ntree->type == NTREE_COMPOSIT) && (node->type == CMP_NODE_GLARE)) {
+ /* Simple forward compat for fix for T50736.
+ * Not ideal (there is no ideal solution here), but should do for now. */
+ NodeGlare *ndg = node->storage;
+ /* Not in undo case. */
+ if (!wd->current) {
+ switch (ndg->type) {
+ case 2: /* Grrrr! magic numbers :( */
+ ndg->angle = ndg->streaks;
+ break;
+ case 0:
+ ndg->angle = ndg->star_45;
+ break;
+ default:
+ break;
+ }
+ }
+ writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
+ }
else {
writestruct_id(wd, DATA, node->typeinfo->storagename, 1, node->storage);
}
@@ -1275,60 +1290,60 @@ static void write_pointcaches(WriteData *wd, ListBase *ptcaches)
}
}
}
-static void write_particlesettings(WriteData *wd, ListBase *idbase)
+
+static void write_particlesettings(WriteData *wd, ParticleSettings *part)
{
- for (ParticleSettings *part = idbase->first; part; part = part->id.next) {
- if (part->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_PA, ParticleSettings, 1, part);
- write_iddata(wd, &part->id);
-
- if (part->adt) {
- write_animdata(wd, part->adt);
- }
- writestruct(wd, DATA, PartDeflect, 1, part->pd);
- writestruct(wd, DATA, PartDeflect, 1, part->pd2);
- writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
+ if (part->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_PA, ParticleSettings, 1, part);
+ write_iddata(wd, &part->id);
- if (part->clumpcurve) {
- write_curvemapping(wd, part->clumpcurve);
- }
- if (part->roughcurve) {
- write_curvemapping(wd, part->roughcurve);
- }
+ if (part->adt) {
+ write_animdata(wd, part->adt);
+ }
+ writestruct(wd, DATA, PartDeflect, 1, part->pd);
+ writestruct(wd, DATA, PartDeflect, 1, part->pd2);
+ writestruct(wd, DATA, EffectorWeights, 1, part->effector_weights);
- for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
- /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
- if (dw->ob != NULL) {
- dw->index = 0;
- if (part->dup_group) { /* can be NULL if lining fails or set to None */
- for (GroupObject *go = part->dup_group->gobject.first;
- go && go->ob != dw->ob;
- go = go->next, dw->index++);
- }
+ if (part->clumpcurve) {
+ write_curvemapping(wd, part->clumpcurve);
+ }
+ if (part->roughcurve) {
+ write_curvemapping(wd, part->roughcurve);
+ }
+
+ for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) {
+ /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */
+ if (dw->ob != NULL) {
+ dw->index = 0;
+ if (part->dup_group) { /* can be NULL if lining fails or set to None */
+ for (GroupObject *go = part->dup_group->gobject.first;
+ go && go->ob != dw->ob;
+ go = go->next, dw->index++);
}
- writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
}
+ writestruct(wd, DATA, ParticleDupliWeight, 1, dw);
+ }
- if (part->boids && part->phystype == PART_PHYS_BOIDS) {
- writestruct(wd, DATA, BoidSettings, 1, part->boids);
+ if (part->boids && part->phystype == PART_PHYS_BOIDS) {
+ writestruct(wd, DATA, BoidSettings, 1, part->boids);
- for (BoidState *state = part->boids->states.first; state; state = state->next) {
- write_boid_state(wd, state);
- }
- }
- if (part->fluid && part->phystype == PART_PHYS_FLUID) {
- writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
+ for (BoidState *state = part->boids->states.first; state; state = state->next) {
+ write_boid_state(wd, state);
}
+ }
+ if (part->fluid && part->phystype == PART_PHYS_FLUID) {
+ writestruct(wd, DATA, SPHFluidSettings, 1, part->fluid);
+ }
- for (int a = 0; a < MAX_MTEX; a++) {
- if (part->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, part->mtex[a]);
- }
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (part->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, part->mtex[a]);
}
}
}
}
+
static void write_particlesystems(WriteData *wd, ListBase *particles)
{
ParticleSystem *psys = particles->first;
@@ -1818,201 +1833,207 @@ static void write_modifiers(WriteData *wd, ListBase *modbase)
writedata(wd, DATA, sizeof(float[3]) * csmd->bind_coords_num, csmd->bind_coords);
}
}
- }
-}
+ else if (md->type == eModifierType_SurfaceDeform) {
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
-static void write_objects(WriteData *wd, ListBase *idbase)
-{
- for (Object *ob = idbase->first; ob; ob = ob->id.next) {
- if (ob->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_OB, Object, 1, ob);
- write_iddata(wd, &ob->id);
-
- if (ob->adt) {
- write_animdata(wd, ob->adt);
- }
+ writestruct(wd, DATA, SDefVert, smd->numverts, smd->verts);
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
- writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
- /* write_effects(wd, &ob->effect); */ /* not used anymore */
- write_properties(wd, &ob->prop);
- write_sensors(wd, &ob->sensors);
- write_controllers(wd, &ob->controllers);
- write_actuators(wd, &ob->actuators);
-
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
- if (arm && ob->pose && arm->act_bone) {
- BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
+ if (smd->verts) {
+ for (int i = 0; i < smd->numverts; i++) {
+ writestruct(wd, DATA, SDefBind, smd->verts[i].numbinds, smd->verts[i].binds);
+
+ if (smd->verts[i].binds) {
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ writedata(wd, DATA, sizeof(int) * smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_inds);
+
+ if (smd->verts[i].binds[j].mode == MOD_SDEF_MODE_CENTROID ||
+ smd->verts[i].binds[j].mode == MOD_SDEF_MODE_LOOPTRI)
+ {
+ writedata(wd, DATA, sizeof(float) * 3, smd->verts[i].binds[j].vert_weights);
+ }
+ else {
+ writedata(wd, DATA, sizeof(float) * smd->verts[i].binds[j].numverts, smd->verts[i].binds[j].vert_weights);
+ }
+ }
+ }
}
}
+ }
+ }
+}
- write_pose(wd, ob->pose);
- write_defgroups(wd, &ob->defbase);
- write_constraints(wd, &ob->constraints);
- write_motionpath(wd, ob->mpath);
+static void write_object(WriteData *wd, Object *ob)
+{
+ if (ob->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_OB, Object, 1, ob);
+ write_iddata(wd, &ob->id);
- writestruct(wd, DATA, PartDeflect, 1, ob->pd);
- writestruct(wd, DATA, SoftBody, 1, ob->soft);
- if (ob->soft) {
- write_pointcaches(wd, &ob->soft->ptcaches);
- writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
- }
- writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft);
+ if (ob->adt) {
+ write_animdata(wd, ob->adt);
+ }
- if (ob->rigidbody_object) {
- /* TODO: if any extra data is added to handle duplis, will need separate function then */
- writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
- }
- if (ob->rigidbody_constraint) {
- writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
- }
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * ob->totcol, ob->mat);
+ writedata(wd, DATA, sizeof(char) * ob->totcol, ob->matbits);
+ /* write_effects(wd, &ob->effect); */ /* not used anymore */
+ write_properties(wd, &ob->prop);
+ write_sensors(wd, &ob->sensors);
+ write_controllers(wd, &ob->controllers);
+ write_actuators(wd, &ob->actuators);
- if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
- writestruct(wd, DATA, ImageUser, 1, ob->iuser);
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+ if (arm && ob->pose && arm->act_bone) {
+ BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
}
+ }
- write_particlesystems(wd, &ob->particlesystem);
- write_modifiers(wd, &ob->modifiers);
+ write_pose(wd, ob->pose);
+ write_defgroups(wd, &ob->defbase);
+ write_constraints(wd, &ob->constraints);
+ write_motionpath(wd, ob->mpath);
- writelist(wd, DATA, LinkData, &ob->pc_ids);
- writelist(wd, DATA, LodLevel, &ob->lodlevels);
+ writestruct(wd, DATA, PartDeflect, 1, ob->pd);
+ writestruct(wd, DATA, SoftBody, 1, ob->soft);
+ if (ob->soft) {
+ write_pointcaches(wd, &ob->soft->ptcaches);
+ writestruct(wd, DATA, EffectorWeights, 1, ob->soft->effector_weights);
+ }
+ writestruct(wd, DATA, BulletSoftBody, 1, ob->bsoft);
- write_previews(wd, ob->preview);
+ if (ob->rigidbody_object) {
+ /* TODO: if any extra data is added to handle duplis, will need separate function then */
+ writestruct(wd, DATA, RigidBodyOb, 1, ob->rigidbody_object);
+ }
+ if (ob->rigidbody_constraint) {
+ writestruct(wd, DATA, RigidBodyCon, 1, ob->rigidbody_constraint);
}
- }
- mywrite_flush(wd);
+ if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
+ writestruct(wd, DATA, ImageUser, 1, ob->iuser);
+ }
+
+ write_particlesystems(wd, &ob->particlesystem);
+ write_modifiers(wd, &ob->modifiers);
+
+ writelist(wd, DATA, LinkData, &ob->pc_ids);
+ writelist(wd, DATA, LodLevel, &ob->lodlevels);
+
+ write_previews(wd, ob->preview);
+ }
}
-static void write_vfonts(WriteData *wd, ListBase *idbase)
+static void write_vfont(WriteData *wd, VFont *vf)
{
- for (VFont *vf = idbase->first; vf; vf = vf->id.next) {
- if (vf->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_VF, VFont, 1, vf);
- write_iddata(wd, &vf->id);
+ if (vf->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_VF, VFont, 1, vf);
+ write_iddata(wd, &vf->id);
- /* direct data */
- if (vf->packedfile) {
- PackedFile *pf = vf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
+ /* direct data */
+ if (vf->packedfile) {
+ PackedFile *pf = vf->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
}
-
- mywrite_flush(wd);
}
-static void write_keys(WriteData *wd, ListBase *idbase)
+static void write_key(WriteData *wd, Key *key)
{
- for (Key *key = idbase->first; key; key = key->id.next) {
- if (key->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_KE, Key, 1, key);
- write_iddata(wd, &key->id);
-
- if (key->adt) {
- write_animdata(wd, key->adt);
- }
+ if (key->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_KE, Key, 1, key);
+ write_iddata(wd, &key->id);
- /* direct data */
- for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
- writestruct(wd, DATA, KeyBlock, 1, kb);
- if (kb->data) {
- writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
- }
+ if (key->adt) {
+ write_animdata(wd, key->adt);
+ }
+
+ /* direct data */
+ for (KeyBlock *kb = key->block.first; kb; kb = kb->next) {
+ writestruct(wd, DATA, KeyBlock, 1, kb);
+ if (kb->data) {
+ writedata(wd, DATA, kb->totelem * key->elemsize, kb->data);
}
}
}
-
- mywrite_flush(wd);
}
-static void write_cameras(WriteData *wd, ListBase *idbase)
+static void write_camera(WriteData *wd, Camera *cam)
{
- for (Camera *cam = idbase->first; cam; cam = cam->id.next) {
- if (cam->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_CA, Camera, 1, cam);
- write_iddata(wd, &cam->id);
-
- if (cam->adt) {
- write_animdata(wd, cam->adt);
- }
+ if (cam->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_CA, Camera, 1, cam);
+ write_iddata(wd, &cam->id);
+
+ if (cam->adt) {
+ write_animdata(wd, cam->adt);
}
}
}
-static void write_mballs(WriteData *wd, ListBase *idbase)
+static void write_mball(WriteData *wd, MetaBall *mb)
{
- for (MetaBall *mb = idbase->first; mb; mb = mb->id.next) {
- if (mb->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_MB, MetaBall, 1, mb);
- write_iddata(wd, &mb->id);
+ if (mb->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_MB, MetaBall, 1, mb);
+ write_iddata(wd, &mb->id);
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
- if (mb->adt) {
- write_animdata(wd, mb->adt);
- }
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * mb->totcol, mb->mat);
+ if (mb->adt) {
+ write_animdata(wd, mb->adt);
+ }
- for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
- writestruct(wd, DATA, MetaElem, 1, ml);
- }
+ for (MetaElem *ml = mb->elems.first; ml; ml = ml->next) {
+ writestruct(wd, DATA, MetaElem, 1, ml);
}
}
}
-static void write_curves(WriteData *wd, ListBase *idbase)
+static void write_curve(WriteData *wd, Curve *cu)
{
- for (Curve *cu = idbase->first; cu; cu = cu->id.next) {
- if (cu->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_CU, Curve, 1, cu);
- write_iddata(wd, &cu->id);
+ if (cu->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_CU, Curve, 1, cu);
+ write_iddata(wd, &cu->id);
- /* direct data */
- writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
- if (cu->adt) {
- write_animdata(wd, cu->adt);
- }
+ /* direct data */
+ writedata(wd, DATA, sizeof(void *) * cu->totcol, cu->mat);
+ if (cu->adt) {
+ write_animdata(wd, cu->adt);
+ }
- if (cu->vfont) {
- writedata(wd, DATA, cu->len + 1, cu->str);
- writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
- writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
+ if (cu->vfont) {
+ writedata(wd, DATA, cu->len + 1, cu->str);
+ writestruct(wd, DATA, CharInfo, cu->len_wchar + 1, cu->strinfo);
+ writestruct(wd, DATA, TextBox, cu->totbox, cu->tb);
+ }
+ else {
+ /* is also the order of reading */
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ writestruct(wd, DATA, Nurb, 1, nu);
}
- else {
- /* is also the order of reading */
- for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
- writestruct(wd, DATA, Nurb, 1, nu);
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
}
- for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
- if (nu->type == CU_BEZIER) {
- writestruct(wd, DATA, BezTriple, nu->pntsu, nu->bezt);
+ else {
+ writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
+ if (nu->knotsu) {
+ writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
}
- else {
- writestruct(wd, DATA, BPoint, nu->pntsu * nu->pntsv, nu->bp);
- if (nu->knotsu) {
- writedata(wd, DATA, KNOTSU(nu) * sizeof(float), nu->knotsu);
- }
- if (nu->knotsv) {
- writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
- }
+ if (nu->knotsv) {
+ writedata(wd, DATA, KNOTSV(nu) * sizeof(float), nu->knotsv);
}
}
}
}
}
-
- mywrite_flush(wd);
}
static void write_dverts(WriteData *wd, int count, MDeformVert *dvlist)
@@ -2129,7 +2150,7 @@ static void write_customdata(
}
}
-static void write_meshes(WriteData *wd, ListBase *idbase)
+static void write_mesh(WriteData *wd, Mesh *mesh)
{
#ifdef USE_BMESH_SAVE_AS_COMPAT
const bool save_for_old_blender = wd->use_mesh_compat; /* option to save with older mesh format */
@@ -2137,383 +2158,341 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
const bool save_for_old_blender = false;
#endif
- for (Mesh *mesh = idbase->first; mesh; mesh = mesh->id.next) {
- CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
-
- if (mesh->id.us > 0 || wd->current) {
- /* write LibData */
- if (!save_for_old_blender) {
- /* write a copy of the mesh, don't modify in place because it is
- * not thread safe for threaded renders that are reading this */
- Mesh *old_mesh = mesh;
- Mesh copy_mesh = *mesh;
- mesh = &copy_mesh;
+ CustomDataLayer *vlayers = NULL, vlayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *elayers = NULL, elayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *flayers = NULL, flayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *llayers = NULL, llayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *players = NULL, players_buff[CD_TEMP_CHUNK_SIZE];
+
+ if (mesh->id.us > 0 || wd->current) {
+ /* write LibData */
+ if (!save_for_old_blender) {
+ /* write a copy of the mesh, don't modify in place because it is
+ * not thread safe for threaded renders that are reading this */
+ Mesh *old_mesh = mesh;
+ Mesh copy_mesh = *mesh;
+ mesh = &copy_mesh;
#ifdef USE_BMESH_SAVE_WITHOUT_MFACE
- /* cache only - don't write */
- mesh->mface = NULL;
- mesh->totface = 0;
- memset(&mesh->fdata, 0, sizeof(mesh->fdata));
+ /* cache only - don't write */
+ mesh->mface = NULL;
+ mesh->totface = 0;
+ memset(&mesh->fdata, 0, sizeof(mesh->fdata));
#endif /* USE_BMESH_SAVE_WITHOUT_MFACE */
- /**
- * Those calls:
- * - Reduce mesh->xdata.totlayer to number of layers to write.
- * - Fill xlayers with those layers to be written.
- * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is
- * a temp local copy!
- */
- CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
- CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ /**
+ * Those calls:
+ * - Reduce mesh->xdata.totlayer to number of layers to write.
+ * - Fill xlayers with those layers to be written.
+ * Note that mesh->xdata is from now on invalid for Blender, but this is why the whole mesh is
+ * a temp local copy!
+ */
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
#ifndef USE_BMESH_SAVE_WITHOUT_MFACE /* Do not copy org fdata in this case!!! */
- CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
#else
- flayers = flayers_buff;
+ flayers = flayers_buff;
#endif
- CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
- CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
- write_iddata(wd, &mesh->id);
+ writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
- /* direct data */
- if (mesh->adt) {
- write_animdata(wd, mesh->adt);
- }
+ /* direct data */
+ if (mesh->adt) {
+ write_animdata(wd, mesh->adt);
+ }
- writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
- writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
+ writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
+ writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect);
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
- /* fdata is really a dummy - written so slots align */
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
+ /* fdata is really a dummy - written so slots align */
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
- /* restore pointer */
- mesh = old_mesh;
- }
- else {
+ /* restore pointer */
+ mesh = old_mesh;
+ }
+ else {
#ifdef USE_BMESH_SAVE_AS_COMPAT
- /* write a copy of the mesh, don't modify in place because it is
- * not thread safe for threaded renders that are reading this */
- Mesh *old_mesh = mesh;
- Mesh copy_mesh = *mesh;
- mesh = &copy_mesh;
-
- mesh->mpoly = NULL;
- mesh->mface = NULL;
- mesh->totface = 0;
- mesh->totpoly = 0;
- mesh->totloop = 0;
- CustomData_reset(&mesh->fdata);
- CustomData_reset(&mesh->pdata);
- CustomData_reset(&mesh->ldata);
- mesh->edit_btmesh = NULL;
- mesh->batch_cache = NULL;
-
- /* now fill in polys to mfaces */
- /* XXX This breaks writing design, by using temp allocated memory, which will likely generate
- * duplicates in stored 'old' addresses.
- * This is very bad, but do not see easy way to avoid this, aside from generating those data
- * outside of save process itself.
- * Maybe we can live with this, though?
- */
- mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &old_mesh->ldata, &old_mesh->pdata,
- mesh->totface, old_mesh->totloop, old_mesh->totpoly);
+ /* write a copy of the mesh, don't modify in place because it is
+ * not thread safe for threaded renders that are reading this */
+ Mesh *old_mesh = mesh;
+ Mesh copy_mesh = *mesh;
+ mesh = &copy_mesh;
+
+ mesh->mpoly = NULL;
+ mesh->mface = NULL;
+ mesh->totface = 0;
+ mesh->totpoly = 0;
+ mesh->totloop = 0;
+ CustomData_reset(&mesh->fdata);
+ CustomData_reset(&mesh->pdata);
+ CustomData_reset(&mesh->ldata);
+ mesh->edit_btmesh = NULL;
+
+ /* now fill in polys to mfaces */
+ /* XXX This breaks writing design, by using temp allocated memory, which will likely generate
+ * duplicates in stored 'old' addresses.
+ * This is very bad, but do not see easy way to avoid this, aside from generating those data
+ * outside of save process itself.
+ * Maybe we can live with this, though?
+ */
+ mesh->totface = BKE_mesh_mpoly_to_mface(&mesh->fdata, &old_mesh->ldata, &old_mesh->pdata,
+ mesh->totface, old_mesh->totloop, old_mesh->totpoly);
- BKE_mesh_update_customdata_pointers(mesh, false);
+ BKE_mesh_update_customdata_pointers(mesh, false);
- CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
- CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
- CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
+ CustomData_file_write_prepare(&mesh->vdata, &vlayers, vlayers_buff, ARRAY_SIZE(vlayers_buff));
+ CustomData_file_write_prepare(&mesh->edata, &elayers, elayers_buff, ARRAY_SIZE(elayers_buff));
+ CustomData_file_write_prepare(&mesh->fdata, &flayers, flayers_buff, ARRAY_SIZE(flayers_buff));
#if 0
- CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
- CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_file_write_prepare(&mesh->ldata, &llayers, llayers_buff, ARRAY_SIZE(llayers_buff));
+ CustomData_file_write_prepare(&mesh->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
#endif
- writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
- write_iddata(wd, &mesh->id);
+ writestruct_at_address(wd, ID_ME, Mesh, 1, old_mesh, mesh);
+ write_iddata(wd, &mesh->id);
- /* direct data */
- if (mesh->adt) {
- write_animdata(wd, mesh->adt);
- }
+ /* direct data */
+ if (mesh->adt) {
+ write_animdata(wd, mesh->adt);
+ }
- writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
- /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
+ writedata(wd, DATA, sizeof(void *) * mesh->totcol, mesh->mat);
+ /* writedata(wd, DATA, sizeof(MSelect) * mesh->totselect, mesh->mselect); */ /* pre-bmesh NULL's */
- write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
- /* harmless for older blender versioins but _not_ writing these keeps file size down */
+ write_customdata(wd, &mesh->id, mesh->totvert, &mesh->vdata, vlayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totedge, &mesh->edata, elayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totface, &mesh->fdata, flayers, -1, 0);
+ /* harmless for older blender versioins but _not_ writing these keeps file size down */
#if 0
- write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
- write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totloop, &mesh->ldata, llayers, -1, 0);
+ write_customdata(wd, &mesh->id, mesh->totpoly, &mesh->pdata, players, -1, 0);
#endif
- CustomData_free(&mesh->fdata, mesh->totface);
- flayers = NULL;
+ CustomData_free(&mesh->fdata, mesh->totface);
+ flayers = NULL;
- /* restore pointer */
- mesh = old_mesh;
+ /* restore pointer */
+ mesh = old_mesh;
#endif /* USE_BMESH_SAVE_AS_COMPAT */
- }
- }
-
- if (vlayers && vlayers != vlayers_buff) {
- MEM_freeN(vlayers);
- }
- if (elayers && elayers != elayers_buff) {
- MEM_freeN(elayers);
- }
- if (flayers && flayers != flayers_buff) {
- MEM_freeN(flayers);
- }
- if (llayers && llayers != llayers_buff) {
- MEM_freeN(llayers);
- }
- if (players && players != players_buff) {
- MEM_freeN(players);
}
}
- mywrite_flush(wd);
+ if (vlayers && vlayers != vlayers_buff) {
+ MEM_freeN(vlayers);
+ }
+ if (elayers && elayers != elayers_buff) {
+ MEM_freeN(elayers);
+ }
+ if (flayers && flayers != flayers_buff) {
+ MEM_freeN(flayers);
+ }
+ if (llayers && llayers != llayers_buff) {
+ MEM_freeN(llayers);
+ }
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
}
-static void write_lattices(WriteData *wd, ListBase *idbase)
+static void write_lattice(WriteData *wd, Lattice *lt)
{
- for (Lattice *lt = idbase->first; lt; lt = lt->id.next) {
- if (lt->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_LT, Lattice, 1, lt);
- write_iddata(wd, &lt->id);
-
- /* write animdata */
- if (lt->adt) {
- write_animdata(wd, lt->adt);
- }
-
- /* direct data */
- writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+ if (lt->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_LT, Lattice, 1, lt);
+ write_iddata(wd, &lt->id);
- write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ /* write animdata */
+ if (lt->adt) {
+ write_animdata(wd, lt->adt);
}
- }
- mywrite_flush(wd);
+ /* direct data */
+ writestruct(wd, DATA, BPoint, lt->pntsu * lt->pntsv * lt->pntsw, lt->def);
+
+ write_dverts(wd, lt->pntsu * lt->pntsv * lt->pntsw, lt->dvert);
+ }
}
-static void write_images(WriteData *wd, ListBase *idbase)
+static void write_image(WriteData *wd, Image *ima)
{
- for (Image *ima = idbase->first; ima; ima = ima->id.next) {
- if (ima->id.us > 0 || wd->current) {
- ImagePackedFile *imapf;
-
- /* Some trickery to keep forward compatibility of packed images. */
- BLI_assert(ima->packedfile == NULL);
- if (ima->packedfiles.first != NULL) {
- imapf = ima->packedfiles.first;
- ima->packedfile = imapf->packedfile;
- }
-
- /* write LibData */
- writestruct(wd, ID_IM, Image, 1, ima);
- write_iddata(wd, &ima->id);
+ if (ima->id.us > 0 || wd->current) {
+ ImagePackedFile *imapf;
- for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
- writestruct(wd, DATA, ImagePackedFile, 1, imapf);
- if (imapf->packedfile) {
- PackedFile *pf = imapf->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
- }
+ /* Some trickery to keep forward compatibility of packed images. */
+ BLI_assert(ima->packedfile == NULL);
+ if (ima->packedfiles.first != NULL) {
+ imapf = ima->packedfiles.first;
+ ima->packedfile = imapf->packedfile;
+ }
- write_previews(wd, ima->preview);
+ /* write LibData */
+ writestruct(wd, ID_IM, Image, 1, ima);
+ write_iddata(wd, &ima->id);
- for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
- writestruct(wd, DATA, ImageView, 1, iv);
+ for (imapf = ima->packedfiles.first; imapf; imapf = imapf->next) {
+ writestruct(wd, DATA, ImagePackedFile, 1, imapf);
+ if (imapf->packedfile) {
+ PackedFile *pf = imapf->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
- writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
+ }
- ima->packedfile = NULL;
+ write_previews(wd, ima->preview);
+
+ for (ImageView *iv = ima->views.first; iv; iv = iv->next) {
+ writestruct(wd, DATA, ImageView, 1, iv);
}
- }
+ writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
- mywrite_flush(wd);
+ ima->packedfile = NULL;
+ }
}
-static void write_textures(WriteData *wd, ListBase *idbase)
+static void write_texture(WriteData *wd, Tex *tex)
{
- for (Tex *tex = idbase->first; tex; tex = tex->id.next) {
- if (tex->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_TE, Tex, 1, tex);
- write_iddata(wd, &tex->id);
-
- if (tex->adt) {
- write_animdata(wd, tex->adt);
- }
+ if (tex->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_TE, Tex, 1, tex);
+ write_iddata(wd, &tex->id);
- /* direct data */
- if (tex->coba) {
- writestruct(wd, DATA, ColorBand, 1, tex->coba);
- }
- if (tex->type == TEX_ENVMAP && tex->env) {
- writestruct(wd, DATA, EnvMap, 1, tex->env);
- }
- if (tex->type == TEX_POINTDENSITY && tex->pd) {
- writestruct(wd, DATA, PointDensity, 1, tex->pd);
- if (tex->pd->coba) {
- writestruct(wd, DATA, ColorBand, 1, tex->pd->coba);
- }
- if (tex->pd->falloff_curve) {
- write_curvemapping(wd, tex->pd->falloff_curve);
- }
- }
- if (tex->type == TEX_VOXELDATA) {
- writestruct(wd, DATA, VoxelData, 1, tex->vd);
- }
- if (tex->type == TEX_OCEAN && tex->ot) {
- writestruct(wd, DATA, OceanTex, 1, tex->ot);
- }
+ if (tex->adt) {
+ write_animdata(wd, tex->adt);
+ }
- /* nodetree is integral part of texture, no libdata */
- if (tex->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
- write_nodetree(wd, tex->nodetree);
+ /* direct data */
+ if (tex->coba) {
+ writestruct(wd, DATA, ColorBand, 1, tex->coba);
+ }
+ if (tex->type == TEX_ENVMAP && tex->env) {
+ writestruct(wd, DATA, EnvMap, 1, tex->env);
+ }
+ if (tex->type == TEX_POINTDENSITY && tex->pd) {
+ writestruct(wd, DATA, PointDensity, 1, tex->pd);
+ if (tex->pd->coba) {
+ writestruct(wd, DATA, ColorBand, 1, tex->pd->coba);
+ }
+ if (tex->pd->falloff_curve) {
+ write_curvemapping(wd, tex->pd->falloff_curve);
}
-
- write_previews(wd, tex->preview);
}
- }
-
- mywrite_flush(wd);
-}
-
-static void write_material_engines_settings(WriteData *wd, ListBase *lb)
-{
- for (MaterialEngineSettings *res = lb->first; res; res = res->next) {
- writestruct(wd, DATA, MaterialEngineSettings, 1, res);
-
- if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
- writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data);
+ if (tex->type == TEX_VOXELDATA) {
+ writestruct(wd, DATA, VoxelData, 1, tex->vd);
}
- else {
- /* No engine matched */
- /* error: don't know how to write this file */
+ if (tex->type == TEX_OCEAN && tex->ot) {
+ writestruct(wd, DATA, OceanTex, 1, tex->ot);
}
+
+ /* nodetree is integral part of texture, no libdata */
+ if (tex->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, tex->nodetree);
+ write_nodetree_nolib(wd, tex->nodetree);
+ }
+
+ write_previews(wd, tex->preview);
}
}
-static void write_materials(WriteData *wd, ListBase *idbase)
+static void write_material(WriteData *wd, Material *ma)
{
- for (Material *ma = idbase->first; ma; ma = ma->id.next) {
- if (ma->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_MA, Material, 1, ma);
- write_iddata(wd, &ma->id);
-
- if (ma->adt) {
- write_animdata(wd, ma->adt);
- }
-
- for (int a = 0; a < MAX_MTEX; a++) {
- if (ma->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
- }
- }
+ if (ma->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_MA, Material, 1, ma);
+ write_iddata(wd, &ma->id);
- if (ma->ramp_col) {
- writestruct(wd, DATA, ColorBand, 1, ma->ramp_col);
- }
- if (ma->ramp_spec) {
- writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec);
- }
+ if (ma->adt) {
+ write_animdata(wd, ma->adt);
+ }
- /* nodetree is integral part of material, no libdata */
- if (ma->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
- write_nodetree(wd, ma->nodetree);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (ma->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, ma->mtex[a]);
}
+ }
- write_previews(wd, ma->preview);
+ if (ma->ramp_col) {
+ writestruct(wd, DATA, ColorBand, 1, ma->ramp_col);
+ }
+ if (ma->ramp_spec) {
+ writestruct(wd, DATA, ColorBand, 1, ma->ramp_spec);
+ }
- write_material_engines_settings(wd, &ma->engines_settings);
+ /* nodetree is integral part of material, no libdata */
+ if (ma->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, ma->nodetree);
+ write_nodetree_nolib(wd, ma->nodetree);
}
+
+ write_previews(wd, ma->preview);
}
}
-static void write_worlds(WriteData *wd, ListBase *idbase)
+static void write_world(WriteData *wd, World *wrld)
{
- for (World *wrld = idbase->first; wrld; wrld = wrld->id.next) {
- if (wrld->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_WO, World, 1, wrld);
- write_iddata(wd, &wrld->id);
-
- if (wrld->adt) {
- write_animdata(wd, wrld->adt);
- }
+ if (wrld->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_WO, World, 1, wrld);
+ write_iddata(wd, &wrld->id);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (wrld->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
- }
- }
+ if (wrld->adt) {
+ write_animdata(wd, wrld->adt);
+ }
- /* nodetree is integral part of world, no libdata */
- if (wrld->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
- write_nodetree(wd, wrld->nodetree);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (wrld->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, wrld->mtex[a]);
}
+ }
- write_previews(wd, wrld->preview);
+ /* nodetree is integral part of world, no libdata */
+ if (wrld->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, wrld->nodetree);
+ write_nodetree_nolib(wd, wrld->nodetree);
}
+
+ write_previews(wd, wrld->preview);
}
}
-static void write_lamps(WriteData *wd, ListBase *idbase)
+static void write_lamp(WriteData *wd, Lamp *la)
{
- for (Lamp *la = idbase->first; la; la = la->id.next) {
- if (la->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_LA, Lamp, 1, la);
- write_iddata(wd, &la->id);
-
- if (la->adt) {
- write_animdata(wd, la->adt);
- }
+ if (la->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_LA, Lamp, 1, la);
+ write_iddata(wd, &la->id);
- /* direct data */
- for (int a = 0; a < MAX_MTEX; a++) {
- if (la->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, la->mtex[a]);
- }
- }
+ if (la->adt) {
+ write_animdata(wd, la->adt);
+ }
- if (la->curfalloff) {
- write_curvemapping(wd, la->curfalloff);
+ /* direct data */
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (la->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, la->mtex[a]);
}
+ }
- /* nodetree is integral part of lamps, no libdata */
- if (la->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
- write_nodetree(wd, la->nodetree);
- }
+ if (la->curfalloff) {
+ write_curvemapping(wd, la->curfalloff);
+ }
- write_previews(wd, la->preview);
+ /* nodetree is integral part of lamps, no libdata */
+ if (la->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, la->nodetree);
+ write_nodetree_nolib(wd, la->nodetree);
}
- }
- mywrite_flush(wd);
+ write_previews(wd, la->preview);
+ }
}
static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
@@ -2569,26 +2548,6 @@ static void write_scene_collection(WriteData *wd, SceneCollection *sc)
}
}
-static void write_collection_engine_settings(WriteData *wd, ListBase *lb)
-{
- for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
- writestruct(wd, DATA, CollectionEngineSettings, 1, ces);
-
- for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) {
- switch (prop->type) {
- case COLLECTION_PROP_TYPE_FLOAT:
- writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop);
- break;
- case COLLECTION_PROP_TYPE_INT:
- writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop);
- break;
- default:
- ; /* error: don't know how to write this file */
- }
- }
- }
-}
-
static void write_layer_collections(WriteData *wd, ListBase *lb)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
@@ -2597,298 +2556,272 @@ static void write_layer_collections(WriteData *wd, ListBase *lb)
writelist(wd, DATA, LinkData, &lc->object_bases);
writelist(wd, DATA, CollectionOverride, &lc->overrides);
- write_collection_engine_settings(wd, &lc->engine_settings);
+ if (lc->properties) {
+ IDP_WriteProperty(lc->properties, wd);
+ }
write_layer_collections(wd, &lc->layer_collections);
}
}
-static void write_render_engines_settings(WriteData *wd, ListBase *lb)
+static void write_scene(WriteData *wd, Scene *sce)
{
- for (RenderEngineSettings *res = lb->first; res; res = res->next) {
- writestruct(wd, DATA, RenderEngineSettings, 1, res);
+ /* write LibData */
+ writestruct(wd, ID_SCE, Scene, 1, sce);
+ write_iddata(wd, &sce->id);
- if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
- writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data);
- }
- else {
- /* No engine matched */
- /* error: don't know how to write this file */
- }
+ if (sce->adt) {
+ write_animdata(wd, sce->adt);
}
-}
-
-static void write_scenes(WriteData *wd, ListBase *scebase)
-{
- for (Scene *sce = scebase->first; sce; sce = sce->id.next) {
- /* write LibData */
- writestruct(wd, ID_SCE, Scene, 1, sce);
- write_iddata(wd, &sce->id);
-
- if (sce->adt) {
- write_animdata(wd, sce->adt);
- }
- write_keyingsets(wd, &sce->keyingsets);
+ write_keyingsets(wd, &sce->keyingsets);
- /* direct data */
- for (BaseLegacy *base = sce->base.first; base; base = base->next) {
- writestruct(wd, DATA, BaseLegacy, 1, base);
- }
+ /* direct data */
+ for (BaseLegacy *base = sce->base.first; base; base = base->next) {
+ writestruct(wd, DATA, BaseLegacy, 1, base);
+ }
- ToolSettings *tos = sce->toolsettings;
- writestruct(wd, DATA, ToolSettings, 1, tos);
- if (tos->vpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->vpaint);
- write_paint(wd, &tos->vpaint->paint);
- }
- if (tos->wpaint) {
- writestruct(wd, DATA, VPaint, 1, tos->wpaint);
- write_paint(wd, &tos->wpaint->paint);
- }
- if (tos->sculpt) {
- writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
- write_paint(wd, &tos->sculpt->paint);
- }
- if (tos->uvsculpt) {
- writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
- write_paint(wd, &tos->uvsculpt->paint);
+ ToolSettings *tos = sce->toolsettings;
+ writestruct(wd, DATA, ToolSettings, 1, tos);
+ if (tos->vpaint) {
+ writestruct(wd, DATA, VPaint, 1, tos->vpaint);
+ write_paint(wd, &tos->vpaint->paint);
+ }
+ if (tos->wpaint) {
+ writestruct(wd, DATA, VPaint, 1, tos->wpaint);
+ write_paint(wd, &tos->wpaint->paint);
+ }
+ if (tos->sculpt) {
+ writestruct(wd, DATA, Sculpt, 1, tos->sculpt);
+ write_paint(wd, &tos->sculpt->paint);
+ }
+ if (tos->uvsculpt) {
+ writestruct(wd, DATA, UvSculpt, 1, tos->uvsculpt);
+ write_paint(wd, &tos->uvsculpt->paint);
+ }
+ /* write grease-pencil drawing brushes to file */
+ writelist(wd, DATA, bGPDbrush, &tos->gp_brushes);
+ for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) {
+ if (brush->cur_sensitivity) {
+ write_curvemapping(wd, brush->cur_sensitivity);
}
- /* write grease-pencil drawing brushes to file */
- writelist(wd, DATA, bGPDbrush, &tos->gp_brushes);
- for (bGPDbrush *brush = tos->gp_brushes.first; brush; brush = brush->next) {
- if (brush->cur_sensitivity) {
- write_curvemapping(wd, brush->cur_sensitivity);
- }
- if (brush->cur_strength) {
- write_curvemapping(wd, brush->cur_strength);
- }
- if (brush->cur_jitter) {
- write_curvemapping(wd, brush->cur_jitter);
- }
+ if (brush->cur_strength) {
+ write_curvemapping(wd, brush->cur_strength);
}
- /* write grease-pencil custom ipo curve to file */
- if (tos->gp_interpolate.custom_ipo) {
- write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ if (brush->cur_jitter) {
+ write_curvemapping(wd, brush->cur_jitter);
}
-
+ }
+ /* write grease-pencil custom ipo curve to file */
+ if (tos->gp_interpolate.custom_ipo) {
+ write_curvemapping(wd, tos->gp_interpolate.custom_ipo);
+ }
- write_paint(wd, &tos->imapaint.paint);
- Editing *ed = sce->ed;
- if (ed) {
- Sequence *seq;
+ write_paint(wd, &tos->imapaint.paint);
- writestruct(wd, DATA, Editing, 1, ed);
+ Editing *ed = sce->ed;
+ if (ed) {
+ Sequence *seq;
- /* reset write flags too */
+ writestruct(wd, DATA, Editing, 1, ed);
- SEQ_BEGIN(ed, seq)
- {
- if (seq->strip) {
- seq->strip->done = false;
- }
- writestruct(wd, DATA, Sequence, 1, seq);
+ /* reset write flags too */
+
+ SEQ_BEGIN(ed, seq)
+ {
+ if (seq->strip) {
+ seq->strip->done = false;
}
- SEQ_END
+ writestruct(wd, DATA, Sequence, 1, seq);
+ }
+ SEQ_END
- SEQ_BEGIN(ed, seq)
- {
- if (seq->strip && seq->strip->done == 0) {
- /* write strip with 'done' at 0 because readfile */
-
- if (seq->effectdata) {
- switch (seq->type) {
- case SEQ_TYPE_COLOR:
- writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_SPEED:
- writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_WIPE:
- writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_GLOW:
- writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_TRANSFORM:
- writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_GAUSSIAN_BLUR:
- writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
- break;
- case SEQ_TYPE_TEXT:
- writestruct(wd, DATA, TextVars, 1, seq->effectdata);
- break;
- }
+ SEQ_BEGIN(ed, seq)
+ {
+ if (seq->strip && seq->strip->done == 0) {
+ /* write strip with 'done' at 0 because readfile */
+
+ if (seq->effectdata) {
+ switch (seq->type) {
+ case SEQ_TYPE_COLOR:
+ writestruct(wd, DATA, SolidColorVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_SPEED:
+ writestruct(wd, DATA, SpeedControlVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_WIPE:
+ writestruct(wd, DATA, WipeVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_GLOW:
+ writestruct(wd, DATA, GlowVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_TRANSFORM:
+ writestruct(wd, DATA, TransformVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ writestruct(wd, DATA, GaussianBlurVars, 1, seq->effectdata);
+ break;
+ case SEQ_TYPE_TEXT:
+ writestruct(wd, DATA, TextVars, 1, seq->effectdata);
+ break;
}
+ }
- writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
-
- Strip *strip = seq->strip;
- writestruct(wd, DATA, Strip, 1, strip);
- if (seq->flag & SEQ_USE_CROP && strip->crop) {
- writestruct(wd, DATA, StripCrop, 1, strip->crop);
- }
- if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
- writestruct(wd, DATA, StripTransform, 1, strip->transform);
- }
- if (seq->flag & SEQ_USE_PROXY && strip->proxy) {
- writestruct(wd, DATA, StripProxy, 1, strip->proxy);
- }
- if (seq->type == SEQ_TYPE_IMAGE) {
- writestruct(wd, DATA, StripElem,
- MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
- strip->stripdata);
- }
- else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
- writestruct(wd, DATA, StripElem, 1, strip->stripdata);
- }
+ writestruct(wd, DATA, Stereo3dFormat, 1, seq->stereo3d_format);
- strip->done = true;
+ Strip *strip = seq->strip;
+ writestruct(wd, DATA, Strip, 1, strip);
+ if (seq->flag & SEQ_USE_CROP && strip->crop) {
+ writestruct(wd, DATA, StripCrop, 1, strip->crop);
}
-
- if (seq->prop) {
- IDP_WriteProperty(seq->prop, wd);
+ if (seq->flag & SEQ_USE_TRANSFORM && strip->transform) {
+ writestruct(wd, DATA, StripTransform, 1, strip->transform);
+ }
+ if (seq->flag & SEQ_USE_PROXY && strip->proxy) {
+ writestruct(wd, DATA, StripProxy, 1, strip->proxy);
+ }
+ if (seq->type == SEQ_TYPE_IMAGE) {
+ writestruct(wd, DATA, StripElem,
+ MEM_allocN_len(strip->stripdata) / sizeof(struct StripElem),
+ strip->stripdata);
+ }
+ else if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD)) {
+ writestruct(wd, DATA, StripElem, 1, strip->stripdata);
}
- write_sequence_modifiers(wd, &seq->modifiers);
+ strip->done = true;
}
- SEQ_END
- /* new; meta stack too, even when its nasty restore code */
- for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
- writestruct(wd, DATA, MetaStack, 1, ms);
+ if (seq->prop) {
+ IDP_WriteProperty(seq->prop, wd);
}
+
+ write_sequence_modifiers(wd, &seq->modifiers);
}
+ SEQ_END
- if (sce->r.avicodecdata) {
- writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
- if (sce->r.avicodecdata->lpFormat) {
- writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
- }
- if (sce->r.avicodecdata->lpParms) {
- writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
- }
+ /* new; meta stack too, even when its nasty restore code */
+ for (MetaStack *ms = ed->metastack.first; ms; ms = ms->next) {
+ writestruct(wd, DATA, MetaStack, 1, ms);
}
+ }
- if (sce->r.qtcodecdata) {
- writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata);
- if (sce->r.qtcodecdata->cdParms) {
- writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
- }
+ if (sce->r.avicodecdata) {
+ writestruct(wd, DATA, AviCodecData, 1, sce->r.avicodecdata);
+ if (sce->r.avicodecdata->lpFormat) {
+ writedata(wd, DATA, sce->r.avicodecdata->cbFormat, sce->r.avicodecdata->lpFormat);
}
- if (sce->r.ffcodecdata.properties) {
- IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
+ if (sce->r.avicodecdata->lpParms) {
+ writedata(wd, DATA, sce->r.avicodecdata->cbParms, sce->r.avicodecdata->lpParms);
}
+ }
- /* writing dynamic list of TimeMarkers to the blend file */
- for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
- writestruct(wd, DATA, TimeMarker, 1, marker);
+ if (sce->r.qtcodecdata) {
+ writestruct(wd, DATA, QuicktimeCodecData, 1, sce->r.qtcodecdata);
+ if (sce->r.qtcodecdata->cdParms) {
+ writedata(wd, DATA, sce->r.qtcodecdata->cdSize, sce->r.qtcodecdata->cdParms);
}
+ }
+ if (sce->r.ffcodecdata.properties) {
+ IDP_WriteProperty(sce->r.ffcodecdata.properties, wd);
+ }
- /* writing dynamic list of TransformOrientations to the blend file */
- for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
- writestruct(wd, DATA, TransformOrientation, 1, ts);
- }
+ /* writing dynamic list of TimeMarkers to the blend file */
+ for (TimeMarker *marker = sce->markers.first; marker; marker = marker->next) {
+ writestruct(wd, DATA, TimeMarker, 1, marker);
+ }
- for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
- writestruct(wd, DATA, SceneRenderLayer, 1, srl);
- for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
- writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
- }
- for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
- writestruct(wd, DATA, FreestyleLineSet, 1, fls);
- }
- }
+ /* writing dynamic list of TransformOrientations to the blend file */
+ for (TransformOrientation *ts = sce->transform_spaces.first; ts; ts = ts->next) {
+ writestruct(wd, DATA, TransformOrientation, 1, ts);
+ }
- /* writing MultiView to the blend file */
- for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
- writestruct(wd, DATA, SceneRenderView, 1, srv);
+ for (SceneRenderLayer *srl = sce->r.layers.first; srl; srl = srl->next) {
+ writestruct(wd, DATA, SceneRenderLayer, 1, srl);
+ for (FreestyleModuleConfig *fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
+ writestruct(wd, DATA, FreestyleModuleConfig, 1, fmc);
}
-
- if (sce->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
- write_nodetree(wd, sce->nodetree);
+ for (FreestyleLineSet *fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
+ writestruct(wd, DATA, FreestyleLineSet, 1, fls);
}
+ }
- write_view_settings(wd, &sce->view_settings);
+ /* writing MultiView to the blend file */
+ for (SceneRenderView *srv = sce->r.views.first; srv; srv = srv->next) {
+ writestruct(wd, DATA, SceneRenderView, 1, srv);
+ }
- /* writing RigidBodyWorld data to the blend file */
- if (sce->rigidbody_world) {
- writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
- writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
- write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
- }
+ if (sce->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, sce->nodetree);
+ write_nodetree_nolib(wd, sce->nodetree);
+ }
- write_previews(wd, sce->preview);
- write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
- write_scene_collection(wd, sce->collection);
+ write_view_settings(wd, &sce->view_settings);
- for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
- writestruct(wd, DATA, SceneLayer, 1, sl);
- writelist(wd, DATA, Base, &sl->object_bases);
- write_layer_collections(wd, &sl->layer_collections);
- }
+ /* writing RigidBodyWorld data to the blend file */
+ if (sce->rigidbody_world) {
+ writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
+ writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
+ write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
+ }
- write_render_engines_settings(wd, &sce->engines_settings);
+ write_previews(wd, sce->preview);
+ write_curvemapping_curves(wd, &sce->r.mblur_shutter_curve);
+ write_scene_collection(wd, sce->collection);
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+ writestruct(wd, DATA, SceneLayer, 1, sl);
+ writelist(wd, DATA, Base, &sl->object_bases);
+ write_layer_collections(wd, &sl->layer_collections);
}
- mywrite_flush(wd);
+ if (sce->collection_properties) {
+ IDP_WriteProperty(sce->collection_properties, wd);
+ }
}
-static void write_gpencils(WriteData *wd, ListBase *lb)
+static void write_gpencil(WriteData *wd, bGPdata *gpd)
{
- for (bGPdata *gpd = lb->first; gpd; gpd = gpd->id.next) {
- if (gpd->id.us > 0 || wd->current) {
- /* write gpd data block to file */
- writestruct(wd, ID_GD, bGPdata, 1, gpd);
- write_iddata(wd, &gpd->id);
-
- if (gpd->adt) {
- write_animdata(wd, gpd->adt);
- }
-
- /* write grease-pencil layers to file */
- writelist(wd, DATA, bGPDlayer, &gpd->layers);
- for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* write this layer's frames to file */
- writelist(wd, DATA, bGPDframe, &gpl->frames);
- for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
- /* write strokes */
- writelist(wd, DATA, bGPDstroke, &gpf->strokes);
- for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
- writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
- }
+ if (gpd->id.us > 0 || wd->current) {
+ /* write gpd data block to file */
+ writestruct(wd, ID_GD, bGPdata, 1, gpd);
+ write_iddata(wd, &gpd->id);
+
+ if (gpd->adt) {
+ write_animdata(wd, gpd->adt);
+ }
+
+ /* write grease-pencil layers to file */
+ writelist(wd, DATA, bGPDlayer, &gpd->layers);
+ for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* write this layer's frames to file */
+ writelist(wd, DATA, bGPDframe, &gpl->frames);
+ for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) {
+ /* write strokes */
+ writelist(wd, DATA, bGPDstroke, &gpf->strokes);
+ for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
+ writestruct(wd, DATA, bGPDspoint, gps->totpoints, gps->points);
}
}
+ }
- /* write grease-pencil palettes */
- writelist(wd, DATA, bGPDpalette, &gpd->palettes);
- for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
- writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
- }
+ /* write grease-pencil palettes */
+ writelist(wd, DATA, bGPDpalette, &gpd->palettes);
+ for (bGPDpalette *palette = gpd->palettes.first; palette; palette = palette->next) {
+ writelist(wd, DATA, bGPDpalettecolor, &palette->colors);
}
}
-
- mywrite_flush(wd);
}
-static void write_windowmanagers(WriteData *wd, ListBase *lb)
+static void write_windowmanager(WriteData *wd, wmWindowManager *wm)
{
- for (wmWindowManager *wm = lb->first; wm; wm = wm->id.next) {
- writestruct(wd, ID_WM, wmWindowManager, 1, wm);
- write_iddata(wd, &wm->id);
+ writestruct(wd, ID_WM, wmWindowManager, 1, wm);
+ write_iddata(wd, &wm->id);
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- writestruct(wd, DATA, wmWindow, 1, win);
- writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
- }
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ writestruct(wd, DATA, wmWindow, 1, win);
+ writestruct(wd, DATA, Stereo3dFormat, 1, win->stereo3d_format);
}
-
- /* typically flushing wouldn't be needed however this data _always_ changes,
- * so flush here for more efficient undo. */
- mywrite_flush(wd);
}
static void write_region(WriteData *wd, ARegion *ar, int spacetype)
@@ -2971,177 +2904,170 @@ static void write_soops(WriteData *wd, SpaceOops *so)
}
}
-static void write_screens(WriteData *wd, ListBase *scrbase)
+static void write_screen(WriteData *wd, bScreen *sc)
{
- for (bScreen *sc = scrbase->first; sc; sc = sc->id.next) {
- /* write LibData */
- /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
- writestruct(wd, ID_SCRN, bScreen, 1, sc);
- write_iddata(wd, &sc->id);
+ /* write LibData */
+ /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
+ writestruct(wd, ID_SCRN, bScreen, 1, sc);
+ write_iddata(wd, &sc->id);
- write_previews(wd, sc->preview);
+ write_previews(wd, sc->preview);
- /* direct data */
- for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
- writestruct(wd, DATA, ScrVert, 1, sv);
- }
-
- for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
- writestruct(wd, DATA, ScrEdge, 1, se);
- }
-
- for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- Panel *pa;
- uiList *ui_list;
- uiPreview *ui_preview;
- PanelCategoryStack *pc_act;
- ARegion *ar;
+ /* direct data */
+ for (ScrVert *sv = sc->vertbase.first; sv; sv = sv->next) {
+ writestruct(wd, DATA, ScrVert, 1, sv);
+ }
- writestruct(wd, DATA, ScrArea, 1, sa);
+ for (ScrEdge *se = sc->edgebase.first; se; se = se->next) {
+ writestruct(wd, DATA, ScrEdge, 1, se);
+ }
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- write_region(wd, ar, sa->spacetype);
+ for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
+ SpaceLink *sl;
+ Panel *pa;
+ uiList *ui_list;
+ uiPreview *ui_preview;
+ PanelCategoryStack *pc_act;
+ ARegion *ar;
- for (pa = ar->panels.first; pa; pa = pa->next) {
- writestruct(wd, DATA, Panel, 1, pa);
- }
+ writestruct(wd, DATA, ScrArea, 1, sa);
- for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
- writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
- }
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ write_region(wd, ar, sa->spacetype);
- for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
- write_uilist(wd, ui_list);
- }
-
- for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
- writestruct(wd, DATA, uiPreview, 1, ui_preview);
- }
+ for (pa = ar->panels.first; pa; pa = pa->next) {
+ writestruct(wd, DATA, Panel, 1, pa);
}
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- for (ar = sl->regionbase.first; ar; ar = ar->next) {
- write_region(wd, ar, sl->spacetype);
- }
-
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BGpic *bgpic;
- writestruct(wd, DATA, View3D, 1, v3d);
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- writestruct(wd, DATA, BGpic, 1, bgpic);
- }
- if (v3d->localvd) {
- writestruct(wd, DATA, View3D, 1, v3d->localvd);
- }
+ for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
+ writestruct(wd, DATA, PanelCategoryStack, 1, pc_act);
+ }
- if (v3d->fx_settings.ssao) {
- writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
- }
- if (v3d->fx_settings.dof) {
- writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
- }
- }
- else if (sl->spacetype == SPACE_IPO) {
- SpaceIpo *sipo = (SpaceIpo *)sl;
- ListBase tmpGhosts = sipo->ghostCurves;
+ for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
+ write_uilist(wd, ui_list);
+ }
- /* temporarily disable ghost curves when saving */
- sipo->ghostCurves.first = sipo->ghostCurves.last = NULL;
+ for (ui_preview = ar->ui_previews.first; ui_preview; ui_preview = ui_preview->next) {
+ writestruct(wd, DATA, uiPreview, 1, ui_preview);
+ }
+ }
- writestruct(wd, DATA, SpaceIpo, 1, sl);
- if (sipo->ads) {
- writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
- }
+ for (sl = sa->spacedata.first; sl; sl = sl->next) {
+ for (ar = sl->regionbase.first; ar; ar = ar->next) {
+ write_region(wd, ar, sl->spacetype);
+ }
- /* reenable ghost curves */
- sipo->ghostCurves = tmpGhosts;
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
+ BGpic *bgpic;
+ writestruct(wd, DATA, View3D, 1, v3d);
+ for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
+ writestruct(wd, DATA, BGpic, 1, bgpic);
}
- else if (sl->spacetype == SPACE_BUTS) {
- writestruct(wd, DATA, SpaceButs, 1, sl);
+ if (v3d->localvd) {
+ writestruct(wd, DATA, View3D, 1, v3d->localvd);
}
- else if (sl->spacetype == SPACE_FILE) {
- SpaceFile *sfile = (SpaceFile *)sl;
- writestruct(wd, DATA, SpaceFile, 1, sl);
- if (sfile->params) {
- writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
- }
- }
- else if (sl->spacetype == SPACE_SEQ) {
- writestruct(wd, DATA, SpaceSeq, 1, sl);
- }
- else if (sl->spacetype == SPACE_OUTLINER) {
- SpaceOops *so = (SpaceOops *)sl;
- write_soops(wd, so);
- }
- else if (sl->spacetype == SPACE_IMAGE) {
- writestruct(wd, DATA, SpaceImage, 1, sl);
- }
- else if (sl->spacetype == SPACE_TEXT) {
- writestruct(wd, DATA, SpaceText, 1, sl);
+ if (v3d->fx_settings.ssao) {
+ writestruct(wd, DATA, GPUSSAOSettings, 1, v3d->fx_settings.ssao);
}
- else if (sl->spacetype == SPACE_SCRIPT) {
- SpaceScript *scr = (SpaceScript *)sl;
- scr->but_refs = NULL;
- writestruct(wd, DATA, SpaceScript, 1, sl);
+ if (v3d->fx_settings.dof) {
+ writestruct(wd, DATA, GPUDOFSettings, 1, v3d->fx_settings.dof);
}
- else if (sl->spacetype == SPACE_ACTION) {
- writestruct(wd, DATA, SpaceAction, 1, sl);
- }
- else if (sl->spacetype == SPACE_NLA) {
- SpaceNla *snla = (SpaceNla *)sl;
+ }
+ else if (sl->spacetype == SPACE_IPO) {
+ SpaceIpo *sipo = (SpaceIpo *)sl;
+ ListBase tmpGhosts = sipo->ghostCurves;
- writestruct(wd, DATA, SpaceNla, 1, snla);
- if (snla->ads) {
- writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
- }
- }
- else if (sl->spacetype == SPACE_TIME) {
- writestruct(wd, DATA, SpaceTime, 1, sl);
- }
- else if (sl->spacetype == SPACE_NODE) {
- SpaceNode *snode = (SpaceNode *)sl;
- bNodeTreePath *path;
- writestruct(wd, DATA, SpaceNode, 1, snode);
+ /* temporarily disable ghost curves when saving */
+ sipo->ghostCurves.first = sipo->ghostCurves.last = NULL;
- for (path = snode->treepath.first; path; path = path->next) {
- writestruct(wd, DATA, bNodeTreePath, 1, path);
- }
- }
- else if (sl->spacetype == SPACE_LOGIC) {
- writestruct(wd, DATA, SpaceLogic, 1, sl);
+ writestruct(wd, DATA, SpaceIpo, 1, sl);
+ if (sipo->ads) {
+ writestruct(wd, DATA, bDopeSheet, 1, sipo->ads);
}
- else if (sl->spacetype == SPACE_CONSOLE) {
- SpaceConsole *con = (SpaceConsole *)sl;
- ConsoleLine *cl;
-
- for (cl = con->history.first; cl; cl = cl->next) {
- /* 'len_alloc' is invalid on write, set from 'len' on read */
- writestruct(wd, DATA, ConsoleLine, 1, cl);
- writedata(wd, DATA, cl->len + 1, cl->line);
- }
- writestruct(wd, DATA, SpaceConsole, 1, sl);
+ /* reenable ghost curves */
+ sipo->ghostCurves = tmpGhosts;
+ }
+ else if (sl->spacetype == SPACE_BUTS) {
+ writestruct(wd, DATA, SpaceButs, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+
+ writestruct(wd, DATA, SpaceFile, 1, sl);
+ if (sfile->params) {
+ writestruct(wd, DATA, FileSelectParams, 1, sfile->params);
}
- else if (sl->spacetype == SPACE_USERPREF) {
- writestruct(wd, DATA, SpaceUserPref, 1, sl);
- }
- else if (sl->spacetype == SPACE_CLIP) {
- writestruct(wd, DATA, SpaceClip, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_SEQ) {
+ writestruct(wd, DATA, SpaceSeq, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOops *so = (SpaceOops *)sl;
+ write_soops(wd, so);
+ }
+ else if (sl->spacetype == SPACE_IMAGE) {
+ writestruct(wd, DATA, SpaceImage, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_TEXT) {
+ writestruct(wd, DATA, SpaceText, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_SCRIPT) {
+ SpaceScript *scr = (SpaceScript *)sl;
+ scr->but_refs = NULL;
+ writestruct(wd, DATA, SpaceScript, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_ACTION) {
+ writestruct(wd, DATA, SpaceAction, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_NLA) {
+ SpaceNla *snla = (SpaceNla *)sl;
+
+ writestruct(wd, DATA, SpaceNla, 1, snla);
+ if (snla->ads) {
+ writestruct(wd, DATA, bDopeSheet, 1, snla->ads);
}
- else if (sl->spacetype == SPACE_INFO) {
- writestruct(wd, DATA, SpaceInfo, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_TIME) {
+ writestruct(wd, DATA, SpaceTime, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_NODE) {
+ SpaceNode *snode = (SpaceNode *)sl;
+ bNodeTreePath *path;
+ writestruct(wd, DATA, SpaceNode, 1, snode);
+
+ for (path = snode->treepath.first; path; path = path->next) {
+ writestruct(wd, DATA, bNodeTreePath, 1, path);
}
- else if (sl->spacetype == SPACE_COLLECTIONS) {
- writestruct(wd, DATA, SpaceCollections, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_LOGIC) {
+ writestruct(wd, DATA, SpaceLogic, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_CONSOLE) {
+ SpaceConsole *con = (SpaceConsole *)sl;
+ ConsoleLine *cl;
+
+ for (cl = con->history.first; cl; cl = cl->next) {
+ /* 'len_alloc' is invalid on write, set from 'len' on read */
+ writestruct(wd, DATA, ConsoleLine, 1, cl);
+ writedata(wd, DATA, cl->len + 1, cl->line);
}
+ writestruct(wd, DATA, SpaceConsole, 1, sl);
+
+ }
+ else if (sl->spacetype == SPACE_USERPREF) {
+ writestruct(wd, DATA, SpaceUserPref, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_CLIP) {
+ writestruct(wd, DATA, SpaceClip, 1, sl);
+ }
+ else if (sl->spacetype == SPACE_INFO) {
+ writestruct(wd, DATA, SpaceInfo, 1, sl);
}
}
}
-
- mywrite_flush(wd);
}
static void write_bone(WriteData *wd, Bone *bone)
@@ -3164,121 +3090,101 @@ static void write_bone(WriteData *wd, Bone *bone)
}
}
-static void write_armatures(WriteData *wd, ListBase *idbase)
+static void write_armature(WriteData *wd, bArmature *arm)
{
- for (bArmature *arm = idbase->first; arm; arm = arm->id.next) {
- if (arm->id.us > 0 || wd->current) {
- writestruct(wd, ID_AR, bArmature, 1, arm);
- write_iddata(wd, &arm->id);
+ if (arm->id.us > 0 || wd->current) {
+ writestruct(wd, ID_AR, bArmature, 1, arm);
+ write_iddata(wd, &arm->id);
- if (arm->adt) {
- write_animdata(wd, arm->adt);
- }
+ if (arm->adt) {
+ write_animdata(wd, arm->adt);
+ }
- /* Direct data */
- for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
- write_bone(wd, bone);
- }
+ /* Direct data */
+ for (Bone *bone = arm->bonebase.first; bone; bone = bone->next) {
+ write_bone(wd, bone);
}
}
-
- mywrite_flush(wd);
}
-static void write_texts(WriteData *wd, ListBase *idbase)
+static void write_text(WriteData *wd, Text *text)
{
- for (Text *text = idbase->first; text; text = text->id.next) {
- if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
- text->flags &= ~TXT_ISEXT;
- }
+ if ((text->flags & TXT_ISMEM) && (text->flags & TXT_ISEXT)) {
+ text->flags &= ~TXT_ISEXT;
+ }
- /* write LibData */
- writestruct(wd, ID_TXT, Text, 1, text);
- write_iddata(wd, &text->id);
+ /* write LibData */
+ writestruct(wd, ID_TXT, Text, 1, text);
+ write_iddata(wd, &text->id);
- if (text->name) {
- writedata(wd, DATA, strlen(text->name) + 1, text->name);
- }
+ if (text->name) {
+ writedata(wd, DATA, strlen(text->name) + 1, text->name);
+ }
- if (!(text->flags & TXT_ISEXT)) {
- /* now write the text data, in two steps for optimization in the readfunction */
- for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
- writestruct(wd, DATA, TextLine, 1, tmp);
- }
+ if (!(text->flags & TXT_ISEXT)) {
+ /* now write the text data, in two steps for optimization in the readfunction */
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
+ writestruct(wd, DATA, TextLine, 1, tmp);
+ }
- for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
- writedata(wd, DATA, tmp->len + 1, tmp->line);
- }
+ for (TextLine *tmp = text->lines.first; tmp; tmp = tmp->next) {
+ writedata(wd, DATA, tmp->len + 1, tmp->line);
}
}
-
- mywrite_flush(wd);
}
-static void write_speakers(WriteData *wd, ListBase *idbase)
+static void write_speaker(WriteData *wd, Speaker *spk)
{
- for (Speaker *spk = idbase->first; spk; spk = spk->id.next) {
- if (spk->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_SPK, Speaker, 1, spk);
- write_iddata(wd, &spk->id);
-
- if (spk->adt) {
- write_animdata(wd, spk->adt);
- }
+ if (spk->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_SPK, Speaker, 1, spk);
+ write_iddata(wd, &spk->id);
+
+ if (spk->adt) {
+ write_animdata(wd, spk->adt);
}
}
}
-static void write_sounds(WriteData *wd, ListBase *idbase)
+static void write_sound(WriteData *wd, bSound *sound)
{
- for (bSound *sound = idbase->first; sound; sound = sound->id.next) {
- if (sound->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_SO, bSound, 1, sound);
- write_iddata(wd, &sound->id);
-
- if (sound->packedfile) {
- PackedFile *pf = sound->packedfile;
- writestruct(wd, DATA, PackedFile, 1, pf);
- writedata(wd, DATA, pf->size, pf->data);
- }
+ if (sound->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_SO, bSound, 1, sound);
+ write_iddata(wd, &sound->id);
+
+ if (sound->packedfile) {
+ PackedFile *pf = sound->packedfile;
+ writestruct(wd, DATA, PackedFile, 1, pf);
+ writedata(wd, DATA, pf->size, pf->data);
}
}
-
- mywrite_flush(wd);
}
-static void write_groups(WriteData *wd, ListBase *idbase)
+static void write_group(WriteData *wd, Group *group)
{
- for (Group *group = idbase->first; group; group = group->id.next) {
- if (group->id.us > 0 || wd->current) {
- /* write LibData */
- writestruct(wd, ID_GR, Group, 1, group);
- write_iddata(wd, &group->id);
+ if (group->id.us > 0 || wd->current) {
+ /* write LibData */
+ writestruct(wd, ID_GR, Group, 1, group);
+ write_iddata(wd, &group->id);
- write_previews(wd, group->preview);
+ write_previews(wd, group->preview);
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- writestruct(wd, DATA, GroupObject, 1, go);
- }
+ for (GroupObject *go = group->gobject.first; go; go = go->next) {
+ writestruct(wd, DATA, GroupObject, 1, go);
}
}
-
- mywrite_flush(wd);
}
-static void write_nodetrees(WriteData *wd, ListBase *idbase)
+static void write_nodetree(WriteData *wd, bNodeTree *ntree)
{
- for (bNodeTree *ntree = idbase->first; ntree; ntree = ntree->id.next) {
- if (ntree->id.us > 0 || wd->current) {
- writestruct(wd, ID_NT, bNodeTree, 1, ntree);
- /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
- * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
- write_iddata(wd, &ntree->id);
+ if (ntree->id.us > 0 || wd->current) {
+ writestruct(wd, ID_NT, bNodeTree, 1, ntree);
+ /* Note that trees directly used by other IDs (materials etc.) are not 'real' ID, they cannot
+ * be linked, etc., so we write actual id data here only, for 'real' ID trees. */
+ write_iddata(wd, &ntree->id);
- write_nodetree(wd, ntree);
- }
+ write_nodetree_nolib(wd, ntree);
}
}
@@ -3352,47 +3258,41 @@ static void customnodes_free_deprecated_data(Main *mainvar)
}
#endif
-static void write_brushes(WriteData *wd, ListBase *idbase)
+static void write_brush(WriteData *wd, Brush *brush)
{
- for (Brush *brush = idbase->first; brush; brush = brush->id.next) {
- if (brush->id.us > 0 || wd->current) {
- writestruct(wd, ID_BR, Brush, 1, brush);
- write_iddata(wd, &brush->id);
+ if (brush->id.us > 0 || wd->current) {
+ writestruct(wd, ID_BR, Brush, 1, brush);
+ write_iddata(wd, &brush->id);
- if (brush->curve) {
- write_curvemapping(wd, brush->curve);
- }
- if (brush->gradient) {
- writestruct(wd, DATA, ColorBand, 1, brush->gradient);
- }
+ if (brush->curve) {
+ write_curvemapping(wd, brush->curve);
+ }
+ if (brush->gradient) {
+ writestruct(wd, DATA, ColorBand, 1, brush->gradient);
}
}
}
-static void write_palettes(WriteData *wd, ListBase *idbase)
+static void write_palette(WriteData *wd, Palette *palette)
{
- for (Palette *palette = idbase->first; palette; palette = palette->id.next) {
- if (palette->id.us > 0 || wd->current) {
- PaletteColor *color;
- writestruct(wd, ID_PAL, Palette, 1, palette);
- write_iddata(wd, &palette->id);
-
- for (color = palette->colors.first; color; color = color->next) {
- writestruct(wd, DATA, PaletteColor, 1, color);
- }
+ if (palette->id.us > 0 || wd->current) {
+ PaletteColor *color;
+ writestruct(wd, ID_PAL, Palette, 1, palette);
+ write_iddata(wd, &palette->id);
+
+ for (color = palette->colors.first; color; color = color->next) {
+ writestruct(wd, DATA, PaletteColor, 1, color);
}
}
}
-static void write_paintcurves(WriteData *wd, ListBase *idbase)
+static void write_paintcurve(WriteData *wd, PaintCurve *pc)
{
- for (PaintCurve *pc = idbase->first; pc; pc = pc->id.next) {
- if (pc->id.us > 0 || wd->current) {
- writestruct(wd, ID_PC, PaintCurve, 1, pc);
- write_iddata(wd, &pc->id);
+ if (pc->id.us > 0 || wd->current) {
+ writestruct(wd, ID_PC, PaintCurve, 1, pc);
+ write_iddata(wd, &pc->id);
- writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
- }
+ writestruct(wd, DATA, PaintCurvePoint, pc->tot_points, pc->points);
}
}
@@ -3434,93 +3334,85 @@ static void write_movieReconstruction(WriteData *wd, MovieTrackingReconstruction
}
}
-static void write_movieclips(WriteData *wd, ListBase *idbase)
+static void write_movieclip(WriteData *wd, MovieClip *clip)
{
- for (MovieClip *clip = idbase->first; clip; clip = clip->id.next) {
- if (clip->id.us > 0 || wd->current) {
- MovieTracking *tracking = &clip->tracking;
- MovieTrackingObject *object;
+ if (clip->id.us > 0 || wd->current) {
+ MovieTracking *tracking = &clip->tracking;
+ MovieTrackingObject *object;
- writestruct(wd, ID_MC, MovieClip, 1, clip);
- write_iddata(wd, &clip->id);
+ writestruct(wd, ID_MC, MovieClip, 1, clip);
+ write_iddata(wd, &clip->id);
- if (clip->adt) {
- write_animdata(wd, clip->adt);
- }
+ if (clip->adt) {
+ write_animdata(wd, clip->adt);
+ }
- write_movieTracks(wd, &tracking->tracks);
- write_moviePlaneTracks(wd, &tracking->plane_tracks);
- write_movieReconstruction(wd, &tracking->reconstruction);
+ write_movieTracks(wd, &tracking->tracks);
+ write_moviePlaneTracks(wd, &tracking->plane_tracks);
+ write_movieReconstruction(wd, &tracking->reconstruction);
- object = tracking->objects.first;
- while (object) {
- writestruct(wd, DATA, MovieTrackingObject, 1, object);
+ object = tracking->objects.first;
+ while (object) {
+ writestruct(wd, DATA, MovieTrackingObject, 1, object);
- write_movieTracks(wd, &object->tracks);
- write_moviePlaneTracks(wd, &object->plane_tracks);
- write_movieReconstruction(wd, &object->reconstruction);
+ write_movieTracks(wd, &object->tracks);
+ write_moviePlaneTracks(wd, &object->plane_tracks);
+ write_movieReconstruction(wd, &object->reconstruction);
- object = object->next;
- }
+ object = object->next;
}
}
-
- mywrite_flush(wd);
}
-static void write_masks(WriteData *wd, ListBase *idbase)
+static void write_mask(WriteData *wd, Mask *mask)
{
- for (Mask *mask = idbase->first; mask; mask = mask->id.next) {
- if (mask->id.us > 0 || wd->current) {
- MaskLayer *masklay;
+ if (mask->id.us > 0 || wd->current) {
+ MaskLayer *masklay;
- writestruct(wd, ID_MSK, Mask, 1, mask);
- write_iddata(wd, &mask->id);
+ writestruct(wd, ID_MSK, Mask, 1, mask);
+ write_iddata(wd, &mask->id);
- if (mask->adt) {
- write_animdata(wd, mask->adt);
- }
+ if (mask->adt) {
+ write_animdata(wd, mask->adt);
+ }
- for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- MaskSpline *spline;
- MaskLayerShape *masklay_shape;
+ for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
+ MaskSpline *spline;
+ MaskLayerShape *masklay_shape;
- writestruct(wd, DATA, MaskLayer, 1, masklay);
+ writestruct(wd, DATA, MaskLayer, 1, masklay);
- for (spline = masklay->splines.first; spline; spline = spline->next) {
- int i;
+ for (spline = masklay->splines.first; spline; spline = spline->next) {
+ int i;
- void *points_deform = spline->points_deform;
- spline->points_deform = NULL;
+ void *points_deform = spline->points_deform;
+ spline->points_deform = NULL;
- writestruct(wd, DATA, MaskSpline, 1, spline);
- writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
+ writestruct(wd, DATA, MaskSpline, 1, spline);
+ writestruct(wd, DATA, MaskSplinePoint, spline->tot_point, spline->points);
- spline->points_deform = points_deform;
+ spline->points_deform = points_deform;
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &spline->points[i];
+ for (i = 0; i < spline->tot_point; i++) {
+ MaskSplinePoint *point = &spline->points[i];
- if (point->tot_uw) {
- writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
- }
+ if (point->tot_uw) {
+ writestruct(wd, DATA, MaskSplinePointUW, point->tot_uw, point->uw);
}
}
+ }
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
- writedata(wd, DATA,
- masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
- masklay_shape->data);
- }
+ for (masklay_shape = masklay->splines_shapes.first;
+ masklay_shape;
+ masklay_shape = masklay_shape->next)
+ {
+ writestruct(wd, DATA, MaskLayerShape, 1, masklay_shape);
+ writedata(wd, DATA,
+ masklay_shape->tot_vert * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE,
+ masklay_shape->data);
}
}
}
-
- mywrite_flush(wd);
}
static void write_linestyle_color_modifiers(WriteData *wd, ListBase *modifiers)
@@ -3777,43 +3669,39 @@ static void write_linestyle_geometry_modifiers(WriteData *wd, ListBase *modifier
}
}
-static void write_linestyles(WriteData *wd, ListBase *idbase)
+static void write_linestyle(WriteData *wd, FreestyleLineStyle *linestyle)
{
- for (FreestyleLineStyle *linestyle = idbase->first; linestyle; linestyle = linestyle->id.next) {
- if (linestyle->id.us > 0 || wd->current) {
- writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
- write_iddata(wd, &linestyle->id);
+ if (linestyle->id.us > 0 || wd->current) {
+ writestruct(wd, ID_LS, FreestyleLineStyle, 1, linestyle);
+ write_iddata(wd, &linestyle->id);
- if (linestyle->adt) {
- write_animdata(wd, linestyle->adt);
- }
+ if (linestyle->adt) {
+ write_animdata(wd, linestyle->adt);
+ }
- write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
- write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
- write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
- write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
- for (int a = 0; a < MAX_MTEX; a++) {
- if (linestyle->mtex[a]) {
- writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
- }
- }
- if (linestyle->nodetree) {
- writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
- write_nodetree(wd, linestyle->nodetree);
+ write_linestyle_color_modifiers(wd, &linestyle->color_modifiers);
+ write_linestyle_alpha_modifiers(wd, &linestyle->alpha_modifiers);
+ write_linestyle_thickness_modifiers(wd, &linestyle->thickness_modifiers);
+ write_linestyle_geometry_modifiers(wd, &linestyle->geometry_modifiers);
+ for (int a = 0; a < MAX_MTEX; a++) {
+ if (linestyle->mtex[a]) {
+ writestruct(wd, DATA, MTex, 1, linestyle->mtex[a]);
}
}
+ if (linestyle->nodetree) {
+ writestruct(wd, DATA, bNodeTree, 1, linestyle->nodetree);
+ write_nodetree_nolib(wd, linestyle->nodetree);
+ }
}
}
-static void write_cachefiles(WriteData *wd, ListBase *idbase)
+static void write_cachefile(WriteData *wd, CacheFile *cache_file)
{
- for (CacheFile *cache_file = idbase->first; cache_file; cache_file = cache_file->id.next) {
- if (cache_file->id.us > 0 || wd->current) {
- writestruct(wd, ID_CF, CacheFile, 1, cache_file);
+ if (cache_file->id.us > 0 || wd->current) {
+ writestruct(wd, ID_CF, CacheFile, 1, cache_file);
- if (cache_file->adt) {
- write_animdata(wd, cache_file->adt);
- }
+ if (cache_file->adt) {
+ write_animdata(wd, cache_file->adt);
}
}
}
@@ -3980,38 +3868,131 @@ static bool write_file_handle(
* avoid thumbnail detecting changes because of this. */
mywrite_flush(wd);
- write_windowmanagers(wd, &mainvar->wm);
- write_screens(wd, &mainvar->screen);
- write_movieclips(wd, &mainvar->movieclip);
- write_masks(wd, &mainvar->mask);
- write_scenes(wd, &mainvar->scene);
- write_curves(wd, &mainvar->curve);
- write_mballs(wd, &mainvar->mball);
- write_images(wd, &mainvar->image);
- write_cameras(wd, &mainvar->camera);
- write_lamps(wd, &mainvar->lamp);
- write_lattices(wd, &mainvar->latt);
- write_vfonts(wd, &mainvar->vfont);
- write_keys(wd, &mainvar->key);
- write_worlds(wd, &mainvar->world);
- write_texts(wd, &mainvar->text);
- write_speakers(wd, &mainvar->speaker);
- write_sounds(wd, &mainvar->sound);
- write_groups(wd, &mainvar->group);
- write_armatures(wd, &mainvar->armature);
- write_actions(wd, &mainvar->action);
- write_objects(wd, &mainvar->object);
- write_materials(wd, &mainvar->mat);
- write_textures(wd, &mainvar->tex);
- write_meshes(wd, &mainvar->mesh);
- write_particlesettings(wd, &mainvar->particle);
- write_nodetrees(wd, &mainvar->nodetree);
- write_brushes(wd, &mainvar->brush);
- write_palettes(wd, &mainvar->palettes);
- write_paintcurves(wd, &mainvar->paintcurves);
- write_gpencils(wd, &mainvar->gpencil);
- write_linestyles(wd, &mainvar->linestyle);
- write_cachefiles(wd, &mainvar->cachefiles);
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a = set_listbasepointers(mainvar, lbarray);
+ while (a--) {
+ ID *id = lbarray[a]->first;
+
+ if (id && GS(id->name) == ID_LI) {
+ continue; /* Libraries are handled separately below. */
+ }
+
+ for (; id; id = id->next) {
+ switch ((ID_Type)GS(id->name)) {
+ case ID_WM:
+ write_windowmanager(wd, (wmWindowManager *)id);
+ break;
+ case ID_SCR:
+ write_screen(wd, (bScreen *)id);
+ break;
+ case ID_MC:
+ write_movieclip(wd, (MovieClip *)id);
+ break;
+ case ID_MSK:
+ write_mask(wd, (Mask *)id);
+ break;
+ case ID_SCE:
+ write_scene(wd, (Scene *)id);
+ break;
+ case ID_CU:
+ write_curve(wd,(Curve *)id);
+ break;
+ case ID_MB:
+ write_mball(wd, (MetaBall *)id);
+ break;
+ case ID_IM:
+ write_image(wd, (Image *)id);
+ break;
+ case ID_CA:
+ write_camera(wd, (Camera *)id);
+ break;
+ case ID_LA:
+ write_lamp(wd, (Lamp *)id);
+ break;
+ case ID_LT:
+ write_lattice(wd, (Lattice *)id);
+ break;
+ case ID_VF:
+ write_vfont(wd, (VFont *)id);
+ break;
+ case ID_KE:
+ write_key(wd, (Key *)id);
+ break;
+ case ID_WO:
+ write_world(wd, (World *)id);
+ break;
+ case ID_TXT:
+ write_text(wd, (Text *)id);
+ break;
+ case ID_SPK:
+ write_speaker(wd, (Speaker *)id);
+ break;
+ case ID_SO:
+ write_sound(wd, (bSound *)id);
+ break;
+ case ID_GR:
+ write_group(wd, (Group *)id);
+ break;
+ case ID_AR:
+ write_armature(wd, (bArmature *)id);
+ break;
+ case ID_AC:
+ write_action(wd, (bAction *)id);
+ break;
+ case ID_OB:
+ write_object(wd, (Object *)id);
+ break;
+ case ID_MA:
+ write_material(wd, (Material *)id);
+ break;
+ case ID_TE:
+ write_texture(wd, (Tex *)id);
+ break;
+ case ID_ME:
+ write_mesh(wd, (Mesh *)id);
+ break;
+ case ID_PA:
+ write_particlesettings(wd, (ParticleSettings *)id);
+ break;
+ case ID_NT:
+ write_nodetree(wd, (bNodeTree *)id);
+ break;
+ case ID_BR:
+ write_brush(wd, (Brush *)id);
+ break;
+ case ID_PAL:
+ write_palette(wd, (Palette *)id);
+ break;
+ case ID_PC:
+ write_paintcurve(wd, (PaintCurve *)id);
+ break;
+ case ID_GD:
+ write_gpencil(wd, (bGPdata *)id);
+ break;
+ case ID_LS:
+ write_linestyle(wd, (FreestyleLineStyle *)id);
+ break;
+ case ID_CF:
+ write_cachefile(wd, (CacheFile *)id);
+ break;
+ case ID_LI:
+ /* Do nothing, handled below - and should never be reached. */
+ BLI_assert(0);
+ break;
+ case ID_IP:
+ /* Do nothing, deprecated. */
+ break;
+ default:
+ /* Should never be reached. */
+ BLI_assert(0);
+ break;
+ }
+ }
+
+ mywrite_flush(wd);
+ }
+
+ /* Special handling, operating over split Mains... */
write_libraries(wd, mainvar->next);
/* So changes above don't cause a 'DNA1' to be detected as changed on undo. */
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 30fefe37f0e..ea24da86626 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -152,6 +152,8 @@ set(SRC
tools/bmesh_path_region.h
tools/bmesh_region_match.c
tools/bmesh_region_match.h
+ tools/bmesh_separate.c
+ tools/bmesh_separate.h
tools/bmesh_triangulate.c
tools/bmesh_triangulate.h
tools/bmesh_wireframe.c
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index f29d280d071..b84a3d5e559 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -192,9 +192,10 @@
*
* These conventions should be used throughout the bmesh module.
*
- * - ``BM_***()`` - High level BMesh API function for use anywhere.
- * - ``bmesh_***()`` - Low level API function.
+ * - ``bmesh_kernel_*()`` - Low level API, for primitive functions that others are built ontop of.
+ * - ``bmesh_***()`` - Low level API function.
* - ``bm_***()`` - 'static' functions, not apart of the API at all, but use prefix since they operate on BMesh data.
+ * - ``BM_***()`` - High level BMesh API function for use anywhere.
* - ``BMO_***()`` - High level operator API function for use anywhere.
* - ``bmo_***()`` - Low level / internal operator API functions.
* - ``_bm_***()`` - Functions which are called via macros only.
diff --git a/source/blender/bmesh/bmesh_tools.h b/source/blender/bmesh/bmesh_tools.h
index 23212dd085e..a537c3b872c 100644
--- a/source/blender/bmesh/bmesh_tools.h
+++ b/source/blender/bmesh/bmesh_tools.h
@@ -43,6 +43,7 @@ extern "C" {
#include "tools/bmesh_path.h"
#include "tools/bmesh_path_region.h"
#include "tools/bmesh_region_match.h"
+#include "tools/bmesh_separate.h"
#include "tools/bmesh_triangulate.h"
#ifdef __cplusplus
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index d1178a198dc..cee5450a37d 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -1021,7 +1021,7 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l)
* \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp,
* (use when flipping normals, disable when mirroring, eg: symmetrize).
*/
-void bmesh_loop_reverse(
+void bmesh_kernel_loop_reverse(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
{
@@ -1438,7 +1438,7 @@ static BMFace *bm_face_create__sfme(BMesh *bm, BMFace *f_example)
*
* \return A BMFace pointer
*/
-BMFace *bmesh_sfme(
+BMFace *bmesh_kernel_split_face_make_edge(
BMesh *bm, BMFace *f, BMLoop *l_v1, BMLoop *l_v2,
BMLoop **r_l,
#ifdef USE_BMESH_HOLES
@@ -1584,7 +1584,7 @@ BMFace *bmesh_sfme(
*
* \return The newly created BMVert pointer.
*/
-BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
+BMVert *bmesh_kernel_split_edge_make_vert(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
{
BMLoop *l_next;
BMEdge *e_new;
@@ -1766,7 +1766,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e)
* faces with just 2 edges. It is up to the caller to decide what to do with
* these faces.
*/
-BMEdge *bmesh_jekv(
+BMEdge *bmesh_kernel_join_edge_kill_vert(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces)
@@ -1920,7 +1920,7 @@ BMEdge *bmesh_jekv(
*
* Collapse an edge, merging surrounding data.
*
- * Unlike #BM_vert_collapse_edge & #bmesh_jekv which only handle 2 valence verts,
+ * Unlike #BM_vert_collapse_edge & #bmesh_kernel_join_edge_kill_vert which only handle 2 valence verts,
* this can handle any number of connected edges/faces.
*
* <pre>
@@ -1932,7 +1932,7 @@ BMEdge *bmesh_jekv(
* +-+-+-+ +-+-+-+
* </pre>
*/
-BMVert *bmesh_jvke(
+BMVert *bmesh_kernel_join_vert_kill_edge(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces)
@@ -2035,7 +2035,7 @@ BMVert *bmesh_jvke(
* In the example A, faces \a f1 and \a f2 are joined by a single edge,
* and the euler can safely be used.
* In example B however, \a f1 and \a f2 are joined by multiple edges and will produce an error.
- * The caller in this case should call #bmesh_jekv on the extra edges
+ * The caller in this case should call #bmesh_kernel_join_edge_kill_vert on the extra edges
* before attempting to fuse \a f1 and \a f2.
*
* \note The order of arguments decides whether or not certain per-face attributes are present
@@ -2044,7 +2044,7 @@ BMVert *bmesh_jvke(
*
* \return A BMFace pointer
*/
-BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
{
BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL;
int newlen = 0, i, f1len = 0, f2len = 0;
@@ -2249,7 +2249,7 @@ bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src)
}
-/** \name BM_vert_separate, bmesh_vert_separate and friends
+/** \name BM_vert_separate, bmesh_kernel_vert_separate and friends
* \{ */
/* BM_edge_face_count(e) >= 1 */
@@ -2269,7 +2269,7 @@ BLI_INLINE bool bm_edge_supports_separate(const BMEdge *e)
*
* \return Success
*/
-void bmesh_vert_separate(
+void bmesh_kernel_vert_separate(
BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
const bool copy_select)
{
@@ -2385,7 +2385,7 @@ void bmesh_vert_separate(
*
* Takes a list of edges, which have been split from their original.
*
- * Any edges which failed to split off in #bmesh_vert_separate will be merged back into the original edge.
+ * Any edges which failed to split off in #bmesh_kernel_vert_separate will be merged back into the original edge.
*
* \param edges_separate
* A list-of-lists, each list is from a single original edge (the first edge is the original),
@@ -2398,7 +2398,7 @@ void bmesh_vert_separate(
* \note this function looks like it could become slow,
* but in common cases its only going to iterate a few times.
*/
-static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
+static void bmesh_kernel_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
{
do {
LinkNode *n_orig = edges_separate->link;
@@ -2418,7 +2418,7 @@ static void bmesh_vert_separate__cleanup(BMesh *bm, LinkNode *edges_separate)
}
/**
- * High level function which wraps both #bmesh_vert_separate and #bmesh_edge_separate
+ * High level function which wraps both #bmesh_kernel_vert_separate and #bmesh_kernel_edge_separate
*/
void BM_vert_separate(
BMesh *bm, BMVert *v,
@@ -2435,7 +2435,7 @@ void BM_vert_separate(
LinkNode *edges_orig = NULL;
do {
BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
BLI_linklist_prepend_alloca(&edges_orig, l_sep->e);
BLI_assert(e != l_sep->e);
} while (bm_edge_supports_separate(e));
@@ -2444,10 +2444,10 @@ void BM_vert_separate(
}
}
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
if (edges_separate) {
- bmesh_vert_separate__cleanup(bm, edges_separate);
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
}
}
@@ -2472,7 +2472,7 @@ void BM_vert_separate_hflag(
LinkNode *edges_orig = NULL;
do {
BMLoop *l_sep = e->l;
- bmesh_edge_separate(bm, e, l_sep, copy_select);
+ bmesh_kernel_edge_separate(bm, e, l_sep, copy_select);
/* trick to avoid looping over separated edges */
if (edges_separate == NULL && edges_orig == NULL) {
e_first = l_sep->e;
@@ -2486,10 +2486,10 @@ void BM_vert_separate_hflag(
}
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
- bmesh_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
+ bmesh_kernel_vert_separate(bm, v, r_vout, r_vout_len, copy_select);
if (edges_separate) {
- bmesh_vert_separate__cleanup(bm, edges_separate);
+ bmesh_kernel_vert_separate__cleanup(bm, edges_separate);
}
}
@@ -2574,7 +2574,7 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src)
* \note Does nothing if \a l_sep is already the only loop in the
* edge radial.
*/
-void bmesh_edge_separate(
+void bmesh_kernel_edge_separate(
BMesh *bm, BMEdge *e, BMLoop *l_sep,
const bool copy_select)
{
@@ -2620,7 +2620,7 @@ void bmesh_edge_separate(
*
* \note Will be a no-op and return original vertex if only two edges at that vertex.
*/
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
+BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = NULL;
BMVert *v_sep = l_sep->v;
@@ -2630,10 +2630,12 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
/* peel the face from the edge radials on both sides of the
* loop vert, disconnecting the face from its fan */
- if (!BM_edge_is_boundary(l_sep->e))
- bmesh_edge_separate(bm, l_sep->e, l_sep, false);
- if (!BM_edge_is_boundary(l_sep->prev->e))
- bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ if (!BM_edge_is_boundary(l_sep->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->e, l_sep, false);
+ }
+ if (!BM_edge_is_boundary(l_sep->prev->e)) {
+ bmesh_kernel_edge_separate(bm, l_sep->prev->e, l_sep->prev, false);
+ }
/* do inline, below */
#if 0
@@ -2681,21 +2683,23 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep)
}
/**
- * A version of #bmesh_urmv_loop that disconnects multiple loops at once.
+ * A version of #bmesh_kernel_unglue_region_make_vert that disconnects multiple loops at once.
* The loops must all share the same vertex, can be in any order
* and are all moved to use a single new vertex - which is returned.
*
* This function handles the details of finding fans boundaries.
*/
-BMVert *bmesh_urmv_loop_multi(
+BMVert *bmesh_kernel_unglue_region_make_vert_multi(
BMesh *bm, BMLoop **larr, int larr_len)
{
BMVert *v_sep = larr[0]->v;
BMVert *v_new;
+ int edges_len = 0;
int i;
- bool is_mixed_any = false;
-
- BLI_SMALLSTACK_DECLARE(edges, BMEdge *);
+ /* any edges not owned by 'larr' loops connected to 'v_sep'? */
+ bool is_mixed_edge_any = false;
+ /* any loops not owned by 'larr' radially connected to 'larr' loop edges? */
+ bool is_mixed_loop_any = false;
#define LOOP_VISIT _FLAG_WALK
#define EDGE_VISIT _FLAG_WALK
@@ -2713,58 +2717,74 @@ BMVert *bmesh_urmv_loop_multi(
* while doing a radial loop (where loops may be adjacent) */
BM_ELEM_API_FLAG_ENABLE(l_sep->next, LOOP_VISIT);
BM_ELEM_API_FLAG_ENABLE(l_sep->prev, LOOP_VISIT);
- }
-
- for (i = 0; i < larr_len; i++) {
- BMLoop *l_sep = larr[i];
BMLoop *loop_pair[2] = {l_sep, l_sep->prev};
- int j;
- for (j = 0; j < ARRAY_SIZE(loop_pair); j++) {
+ for (int j = 0; j < ARRAY_SIZE(loop_pair); j++) {
BMEdge *e = loop_pair[j]->e;
if (!BM_ELEM_API_FLAG_TEST(e, EDGE_VISIT)) {
- BMLoop *l_iter, *l_first;
- bool is_mixed = false;
-
BM_ELEM_API_FLAG_ENABLE(e, EDGE_VISIT);
+ edges_len += 1;
+ }
+ }
+ }
- l_iter = l_first = e->l;
+ BMEdge **edges = BLI_array_alloca(edges, edges_len);
+ STACK_DECLARE(edges);
+
+ STACK_INIT(edges, edges_len);
+
+ {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = v_sep->e;
+ do {
+ if (BM_ELEM_API_FLAG_TEST(e_iter, EDGE_VISIT)) {
+ BMLoop *l_iter, *l_first;
+ bool is_mixed_loop = false;
+
+ l_iter = l_first = e_iter->l;
do {
if (!BM_ELEM_API_FLAG_TEST(l_iter, LOOP_VISIT)) {
- is_mixed = true;
- is_mixed_any = true;
+ is_mixed_loop = true;
break;
}
} while ((l_iter = l_iter->radial_next) != l_first);
- if (is_mixed) {
+ if (is_mixed_loop) {
/* ensure the first loop is one we don't own so we can do a quick check below
* on the edge's loop-flag to see if the edge is mixed or not. */
- e->l = l_iter;
+ e_iter->l = l_iter;
+
+ is_mixed_loop_any = true;
}
- BLI_SMALLSTACK_PUSH(edges, e);
+
+ STACK_PUSH(edges, e_iter);
}
- }
+ else {
+ /* at least one edge attached isn't connected to our loops */
+ is_mixed_edge_any = true;
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v_sep)) != e_first);
}
- if (is_mixed_any == false) {
+ BLI_assert(edges_len == STACK_SIZE(edges));
+
+ if (is_mixed_loop_any == false && is_mixed_edge_any == false) {
/* all loops in 'larr' are the sole owners of their edges.
* nothing to split away from, this is a no-op */
v_new = v_sep;
}
else {
- BMEdge *e;
-
- BLI_assert(!BLI_SMALLSTACK_IS_EMPTY(edges));
-
v_new = BM_vert_create(bm, v_sep->co, v_sep, BM_CREATE_NOP);
- while ((e = BLI_SMALLSTACK_POP(edges))) {
+
+ for (i = 0; i < STACK_SIZE(edges); i++) {
+ BMEdge *e = edges[i];
BMLoop *l_iter, *l_first, *l_next;
BMEdge *e_new;
/* disable so copied edge isn't left dirty (loop edges are cleared last too) */
BM_ELEM_API_FLAG_DISABLE(e, EDGE_VISIT);
+ /* will always be false when (is_mixed_loop_any == false) */
if (!BM_ELEM_API_FLAG_TEST(e->l, LOOP_VISIT)) {
/* edge has some loops owned by us, some owned by other loops */
BMVert *e_new_v_pair[2];
@@ -2853,9 +2873,9 @@ static void bmesh_edge_vert_swap__recursive(BMEdge *e, BMVert *v_dst, BMVert *v_
/**
* This function assumes l_sep is apart of a larger fan which has already been
- * isolated by calling bmesh_edge_separate to segregate it radially.
+ * isolated by calling #bmesh_kernel_edge_separate to segregate it radially.
*/
-BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep)
+BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
BMVert *v_new = BM_vert_create(bm, l_sep->v->co, l_sep->v, BM_CREATE_NOP);
/* passing either 'l_sep->e', 'l_sep->prev->e' will work */
@@ -2864,20 +2884,6 @@ BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep)
return v_new;
}
-
-/**
- * \brief Unglue Region Make Vert (URMV)
- *
- * Disconnects f_sep from the vertex fan at \a v_sep
- *
- * \return The newly created BMVert
- */
-BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep)
-{
- BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep);
- return bmesh_urmv_loop(bm, l);
-}
-
/**
* Avoid calling this where possible,
* low level function so both face pointers remain intact but point to swapped data.
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index f72e9d7b198..fb6b66809f3 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -64,21 +64,16 @@ void BM_face_kill(BMesh *bm, BMFace *f);
void BM_edge_kill(BMesh *bm, BMEdge *e);
void BM_vert_kill(BMesh *bm, BMVert *v);
-void bmesh_edge_separate(
- BMesh *bm, BMEdge *e, BMLoop *l_sep,
- const bool copy_select);
bool BM_edge_splice(BMesh *bm, BMEdge *e_dst, BMEdge *e_src);
bool BM_vert_splice(BMesh *bm, BMVert *v_dst, BMVert *v_src);
bool BM_vert_splice_check_double(BMVert *v_a, BMVert *v_b);
-void bmesh_vert_separate(
- BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
- const bool copy_select);
-
-void bmesh_loop_reverse(
+void bmesh_kernel_loop_reverse(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip);
+void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del);
void BM_vert_separate(
BMesh *bm, BMVert *v, BMEdge **e_in, int e_in_len, const bool copy_select,
@@ -90,34 +85,43 @@ void BM_vert_separate_wire_hflag(
BMesh *bm, BMVert *v_dst, BMVert *v_src,
const char hflag);
-/* EULER API - For modifying structure */
-BMFace *bmesh_sfme(
+/**
+ * BMesh Kernel: For modifying structure.
+ *
+ * Names are on the verbose side but these are only for low-level access.
+ */
+void bmesh_kernel_vert_separate(
+ BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len,
+ const bool copy_select);
+void bmesh_kernel_edge_separate(
+ BMesh *bm, BMEdge *e, BMLoop *l_sep,
+ const bool copy_select);
+
+BMFace *bmesh_kernel_split_face_make_edge(
BMesh *bm, BMFace *f,
BMLoop *l1, BMLoop *l2,
BMLoop **r_l,
#ifdef USE_BMESH_HOLES
- ListBase *holes,
+ ListBase *holes,
#endif
- BMEdge *example,
- const bool no_double
- );
+ BMEdge *example,
+ const bool no_double
+ );
-BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
-BMEdge *bmesh_jekv(
+BMVert *bmesh_kernel_split_edge_make_vert(
+ BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e);
+BMEdge *bmesh_kernel_join_edge_kill_vert(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_splice,
const bool kill_degenerate_faces);
-BMVert *bmesh_jvke(
+BMVert *bmesh_kernel_join_vert_kill_edge(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool check_edge_double,
const bool kill_degenerate_faces);
-BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
-BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep);
-BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep);
-BMVert *bmesh_urmv_loop_multi(
- BMesh *bm, BMLoop **larr, int larr_len);
-BMVert *bmesh_urmv_loop_region(BMesh *bm, BMLoop *l_sep);
+BMFace *bmesh_kernel_join_face_kill_edge(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
-void bmesh_face_swap_data(BMFace *f_a, BMFace *f_b);
+BMVert *bmesh_kernel_unglue_region_make_vert(BMesh *bm, BMLoop *l_sep);
+BMVert *bmesh_kernel_unglue_region_make_vert_multi(BMesh *bm, BMLoop **larr, int larr_len);
+BMVert *bmesh_kernel_unglue_region_make_vert_multi_isolated(BMesh *bm, BMLoop *l_sep);
#endif /* __BMESH_CORE_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index 57a6d8d2e1a..e9fb6a28154 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -486,8 +486,7 @@ static void bm_mesh_edges_sharp_tag(
BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle,
float (*r_lnos)[3])
{
- BMIter eiter, viter;
- BMVert *v;
+ BMIter eiter;
BMEdge *e;
int i;
@@ -498,19 +497,13 @@ static void bm_mesh_edges_sharp_tag(
}
{
- char htype = BM_LOOP;
+ char htype = BM_VERT | BM_LOOP;
if (fnos) {
htype |= BM_FACE;
}
BM_mesh_elem_index_ensure(bm, htype);
}
- /* Clear all vertices' tags (means they are all smooth for now). */
- BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
- BM_elem_index_set(v, i); /* set_inline */
- BM_elem_flag_disable(v, BM_ELEM_TAG);
- }
-
/* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were
* all smooth).
*/
@@ -551,20 +544,45 @@ static void bm_mesh_edges_sharp_tag(
no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no;
copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no);
}
- else {
- /* Sharp edge, tag its verts as such. */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ }
+ }
+
+ bm->elem_index_dirty &= ~BM_EDGE;
+}
+
+/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not.
+ * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */
+static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr)
+{
+ BMLoop *lfan_pivot_next = l_curr;
+ BMEdge *e_next = l_curr->e;
+
+ BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG));
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
+
+ while (true) {
+ /* Much simpler than in sibling code with basic Mesh data! */
+ lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next);
+
+ if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) {
+ /* Sharp loop/edge, so not a cyclic smooth fan... */
+ return false;
+ }
+ /* Smooth loop/edge... */
+ else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) {
+ if (lfan_pivot_next == l_curr) {
+ /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can
+ * use initial l_curr/l_prev edge as start for this smooth fan. */
+ return true;
}
+ /* ... already checked in some previous looping, we can abort. */
+ return false;
}
else {
- /* Sharp edge, tag its verts as such. */
- BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
- BM_elem_flag_enable(e->v2, BM_ELEM_TAG);
+ /* ... we can skip it in future, and keep checking the smooth fan. */
+ BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG);
}
}
-
- bm->elem_index_dirty &= ~(BM_EDGE | BM_VERT);
}
/* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c
@@ -587,13 +605,11 @@ static void bm_mesh_loops_calc_normals(
BLI_Stack *edge_vectors = NULL;
{
- char htype = BM_LOOP;
+ char htype = 0;
if (vcos) {
htype |= BM_VERT;
}
- if (fnos) {
- htype |= BM_FACE;
- }
+ /* Face/Loop indices are set inline below. */
BM_mesh_elem_index_ensure(bm, htype);
}
@@ -606,6 +622,21 @@ static void bm_mesh_loops_calc_normals(
edge_vectors = BLI_stack_new(sizeof(float[3]), __func__);
}
+ /* Clear all loops' tags (means none are to be skipped for now). */
+ int index_face, index_loop = 0;
+ BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) {
+ BMLoop *l_curr, *l_first;
+
+ BM_elem_index_set(f_curr, index_face); /* set_inline */
+
+ l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
+ do {
+ BM_elem_index_set(l_curr, index_loop++); /* set_inline */
+ BM_elem_flag_disable(l_curr, BM_ELEM_TAG);
+ } while ((l_curr = l_curr->next) != l_first);
+ }
+ bm->elem_index_dirty &= ~(BM_FACE|BM_LOOP);
+
/* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't).
* Now, time to generate the normals.
*/
@@ -614,16 +645,16 @@ static void bm_mesh_loops_calc_normals(
l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr);
do {
+ /* A smooth edge, we have to check for cyclic smooth fan case.
+ * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as
+ * 'entry point', otherwise we can skip it. */
+ /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack,
+ * to avoid having to fan again around the vert during actual computation of clnor & clnorspace.
+ * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop()
+ * is quite cheap in term of CPU cycles, so really think it's not worth it. */
if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
- (!r_lnors_spacearr || BM_elem_flag_test(l_curr->v, BM_ELEM_TAG)))
+ (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr)))
{
- /* A smooth edge, and we are not generating lnors_spacearr, or the related vertex is sharp.
- * We skip it because it is either:
- * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit
- * one of its ends, i.e. one of its two sharp edges), or...
- * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex
- * are just fine!
- */
}
else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) &&
!BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG))
@@ -1481,23 +1512,6 @@ int BM_mesh_elem_count(BMesh *bm, const char htype)
}
}
-/**
- * Special case: Python uses custom-data layers to hold PyObject references.
- * These have to be kept in-place, else the PyObject's we point to, wont point back to us.
- *
- * \note ``ele_src`` Is a duplicate, so we don't need to worry about getting in a feedback loop.
- *
- * \note If there are other customdata layers which need this functionality, it should be generalized.
- * However #BM_mesh_remap is currently the only place where this is done.
- */
-static void bm_mesh_remap_cd_update(
- BMHeader *ele_dst, BMHeader *ele_src,
- const int cd_elem_pyptr)
-{
- void **pyptr_dst_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_dst), cd_elem_pyptr);
- void **pyptr_src_p = BM_ELEM_CD_GET_VOID_P(((BMElem *)ele_src), cd_elem_pyptr);
- *pyptr_dst_p = *pyptr_src_p;
-}
/**
* Remaps the vertices, edges and/or faces of the bmesh as indicated by vert/edge/face_idx arrays
@@ -1539,6 +1553,8 @@ void BM_mesh_remap(
BMVert **verts_pool, *verts_copy, **vep;
int i, totvert = bm->totvert;
const unsigned int *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_vert_pyptr = CustomData_get_offset(&bm->vdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1547,9 +1563,14 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
verts_pool = bm->vtable;
verts_copy = MEM_mallocN(sizeof(BMVert) * totvert, "BM_mesh_remap verts copy");
+ void **pyptrs = (cd_vert_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totvert, __func__) : NULL;
for (i = totvert, ve = verts_copy + totvert - 1, vep = verts_pool + totvert - 1; i--; ve--, vep--) {
*ve = **vep;
/* printf("*vep: %p, verts_pool[%d]: %p\n", *vep, i, verts_pool[i]);*/
+ if (cd_vert_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ve), cd_vert_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1562,13 +1583,17 @@ void BM_mesh_remap(
/* printf("mapping vert from %d to %d (%p/%p to %p)\n", i, *new_idx, *vep, verts_pool[i], new_vep);*/
BLI_ghash_insert(vptr_map, *vep, new_vep);
if (cd_vert_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*vep)->head, &new_vep->head, cd_vert_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_vep), cd_vert_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
bm->elem_index_dirty |= BM_VERT;
bm->elem_table_dirty |= BM_VERT;
MEM_freeN(verts_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* Remap Edges */
@@ -1576,6 +1601,8 @@ void BM_mesh_remap(
BMEdge **edges_pool, *edges_copy, **edp;
int i, totedge = bm->totedge;
const unsigned int *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_edge_pyptr = CustomData_get_offset(&bm->edata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1584,8 +1611,13 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
edges_pool = bm->etable;
edges_copy = MEM_mallocN(sizeof(BMEdge) * totedge, "BM_mesh_remap edges copy");
+ void **pyptrs = (cd_edge_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totedge, __func__) : NULL;
for (i = totedge, ed = edges_copy + totedge - 1, edp = edges_pool + totedge - 1; i--; ed--, edp--) {
*ed = **edp;
+ if (cd_edge_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)ed), cd_edge_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1598,13 +1630,17 @@ void BM_mesh_remap(
BLI_ghash_insert(eptr_map, *edp, new_edp);
/* printf("mapping edge from %d to %d (%p/%p to %p)\n", i, *new_idx, *edp, edges_pool[i], new_edp);*/
if (cd_edge_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*edp)->head, &new_edp->head, cd_edge_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_edp), cd_edge_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
bm->elem_index_dirty |= BM_EDGE;
bm->elem_table_dirty |= BM_EDGE;
MEM_freeN(edges_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* Remap Faces */
@@ -1612,6 +1648,8 @@ void BM_mesh_remap(
BMFace **faces_pool, *faces_copy, **fap;
int i, totface = bm->totface;
const unsigned int *new_idx;
+ /* Special case: Python uses custom - data layers to hold PyObject references.
+ * These have to be kept in - place, else the PyObject's we point to, wont point back to us. */
const int cd_poly_pyptr = CustomData_get_offset(&bm->pdata, CD_BM_ELEM_PYPTR);
/* Init the old-to-new vert pointers mapping */
@@ -1620,8 +1658,13 @@ void BM_mesh_remap(
/* Make a copy of all vertices. */
faces_pool = bm->ftable;
faces_copy = MEM_mallocN(sizeof(BMFace) * totface, "BM_mesh_remap faces copy");
+ void **pyptrs = (cd_poly_pyptr != -1) ? MEM_mallocN(sizeof(void *) * totface, __func__) : NULL;
for (i = totface, fa = faces_copy + totface - 1, fap = faces_pool + totface - 1; i--; fa--, fap--) {
*fa = **fap;
+ if (cd_poly_pyptr != -1) {
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)fa), cd_poly_pyptr);
+ pyptrs[i] = *pyptr;
+ }
}
/* Copy back verts to their new place, and update old2new pointers mapping. */
@@ -1633,7 +1676,8 @@ void BM_mesh_remap(
*new_fap = *fa;
BLI_ghash_insert(fptr_map, *fap, new_fap);
if (cd_poly_pyptr != -1) {
- bm_mesh_remap_cd_update(&(*fap)->head, &new_fap->head, cd_poly_pyptr);
+ void **pyptr = BM_ELEM_CD_GET_VOID_P(((BMElem *)new_fap), cd_poly_pyptr);
+ *pyptr = pyptrs[*new_idx];
}
}
@@ -1641,6 +1685,9 @@ void BM_mesh_remap(
bm->elem_table_dirty |= BM_FACE;
MEM_freeN(faces_copy);
+ if (pyptrs) {
+ MEM_freeN(pyptrs);
+ }
}
/* And now, fix all vertices/edges/faces/loops pointers! */
@@ -2008,4 +2055,4 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags)
vpool_dst, epool_dst, NULL, fpool_dst);
bm->use_toolflags = use_toolflags;
-} \ No newline at end of file
+}
diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c
index 500da6b8788..1cd51528e06 100644
--- a/source/blender/bmesh/intern/bmesh_mods.c
+++ b/source/blender/bmesh/intern/bmesh_mods.c
@@ -234,7 +234,7 @@ BMFace *BM_faces_join_pair(BMesh *bm, BMLoop *l_a, BMLoop *l_b, const bool do_de
if (l_a->v == l_b->v) {
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
- bmesh_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
+ bmesh_kernel_loop_reverse(bm, l_b->f, cd_loop_mdisp_offset, true);
}
BMFace *faces[2] = {l_a->f, l_b->f};
@@ -288,9 +288,9 @@ BMFace *BM_face_split(
}
#ifdef USE_BMESH_HOLES
- f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, NULL, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, NULL, example, no_double);
#else
- f_new = bmesh_sfme(bm, f, l_a, l_b, r_l, example, no_double);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, r_l, example, no_double);
#endif
if (f_new) {
@@ -370,19 +370,19 @@ BMFace *BM_face_split_n(
f_tmp = BM_face_copy(bm, bm, f, true, true);
#ifdef USE_BMESH_HOLES
- f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, NULL, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, NULL, example, false);
#else
- f_new = bmesh_sfme(bm, f, l_a, l_b, &l_new, example, false);
+ f_new = bmesh_kernel_split_face_make_edge(bm, f, l_a, l_b, &l_new, example, false);
#endif
- /* bmesh_sfme returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
+ /* bmesh_kernel_split_face_make_edge returns in 'l_new' a Loop for f_new going from 'v_a' to 'v_b'.
* The radial_next is for 'f' and goes from 'v_b' to 'v_a' */
if (f_new) {
e = l_new->e;
for (i = 0; i < n; i++) {
- v_new = bmesh_semv(bm, v_b, e, &e_new);
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v_b, e, &e_new);
BLI_assert(v_new != NULL);
- /* bmesh_semv returns in 'e_new' the edge going from 'v_new' to 'v_b' */
+ /* bmesh_kernel_split_edge_make_vert returns in 'e_new' the edge going from 'v_new' to 'v_b' */
copy_v3_v3(v_new->co, cos[i]);
/* interpolate the loop data for the loops with (v == v_new), using orig face */
@@ -507,7 +507,7 @@ BMEdge *BM_vert_collapse_faces(
/* single face or no faces */
/* same as BM_vert_collapse_edge() however we already
* have vars to perform this operation so don't call. */
- e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
/* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */
}
@@ -542,7 +542,7 @@ BMEdge *BM_vert_collapse_edge(
BMVert *tv2 = BM_edge_other_vert(e2, v_kill);
if (tv2) {
/* only action, other calls here only get the edge to return */
- e_new = bmesh_jekv(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ e_new = bmesh_kernel_join_edge_kill_vert(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
}
}
@@ -564,7 +564,7 @@ BMVert *BM_edge_collapse(
BMesh *bm, BMEdge *e_kill, BMVert *v_kill,
const bool do_del, const bool kill_degenerate_faces)
{
- return bmesh_jvke(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
+ return bmesh_kernel_join_vert_kill_edge(bm, e_kill, v_kill, do_del, true, kill_degenerate_faces);
}
/**
@@ -616,7 +616,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float fac)
}
v_other = BM_edge_other_vert(e, v);
- v_new = bmesh_semv(bm, v, e, &e_new);
+ v_new = bmesh_kernel_split_edge_make_vert(bm, v, e, &e_new);
if (r_e != NULL) {
*r_e = e_new;
}
@@ -1090,23 +1090,18 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f
/**
* \brief Rip a single face from a vertex fan
*/
-BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv)
+BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_urmv(bm, sf, sv);
+ return bmesh_kernel_unglue_region_make_vert(bm, l_sep);
}
-/**
- * \brief Rip a single face from a vertex fan
- *
- * \note same as #BM_face_vert_separate but faster (avoids a loop lookup)
- */
-BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl)
+BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep)
{
- return bmesh_urmv_loop(bm, sl);
+ return bmesh_kernel_unglue_region_make_vert_multi_isolated(bm, l_sep);
}
-BMVert *BM_face_loop_separate_multi(
- BMesh *bm, BMLoop **larr, int larr_len)
+BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len)
{
- return bmesh_urmv_loop_multi(bm, larr, larr_len);
+ return bmesh_kernel_unglue_region_make_vert_multi(bm, larr, larr_len);
}
+
diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h
index 5e95e9a2cc7..330a714418d 100644
--- a/source/blender/bmesh/intern/bmesh_mods.h
+++ b/source/blender/bmesh/intern/bmesh_mods.h
@@ -86,9 +86,8 @@ enum {
};
-BMVert *BM_face_vert_separate(BMesh *bm, BMFace *sf, BMVert *sv);
-BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *sl);
-BMVert *BM_face_loop_separate_multi(
- BMesh *bm, BMLoop **larr, int larr_len);
+BMVert *BM_face_loop_separate(BMesh *bm, BMLoop *l_sep);
+BMVert *BM_face_loop_separate_multi_isolated(BMesh *bm, BMLoop *l_sep);
+BMVert *BM_face_loop_separate_multi(BMesh *bm, BMLoop **larr, int larr_len);
#endif /* __BMESH_MODS_H__ */
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index 0d0fdda2c4c..6b388a75436 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -1284,7 +1284,7 @@ static BMOpDefine bmo_bisect_plane_def = {
{"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */
{{'\0'}},
},
- {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */
+ {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */
{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */
{{'\0'}}},
bmo_bisect_plane_exec,
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index 6acd790fc0c..78ee7589d23 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -844,7 +844,7 @@ void BM_face_normal_flip_ex(
BMesh *bm, BMFace *f,
const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip)
{
- bmesh_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
+ bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip);
negate_v3(f->no);
}
diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c
index bed1ea5cb94..2c80ff651b8 100644
--- a/source/blender/bmesh/operators/bmo_bisect_plane.c
+++ b/source/blender/bmesh/operators/bmo_bisect_plane.c
@@ -38,7 +38,8 @@
#include "intern/bmesh_operators_private.h" /* own include */
#define ELE_NEW 1
-#define ELE_INPUT 2
+#define ELE_CUT 2
+#define ELE_INPUT 4
void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
{
@@ -69,7 +70,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
BM_mesh_bisect_plane(bm, plane, use_snap_center, true,
- ELE_NEW, dist);
+ ELE_CUT, ELE_NEW, dist);
if (clear_outer || clear_inner) {
@@ -108,5 +109,5 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op)
}
BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW);
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT);
}
diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c
index 56639a097b6..8048add84d4 100644
--- a/source/blender/bmesh/operators/bmo_dupe.c
+++ b/source/blender/bmesh/operators/bmo_dupe.c
@@ -378,6 +378,10 @@ void BMO_dupe_from_flag(BMesh *bm, int htype, const char hflag)
* BMOP_DUPE_VOUTPUT: Buffer containing pointers to the split mesh vertices
* BMOP_DUPE_EOUTPUT: Buffer containing pointers to the split mesh edges
* BMOP_DUPE_FOUTPUT: Buffer containing pointers to the split mesh faces
+ *
+ * \note Lower level uses of this operator may want to use #BM_mesh_separate_faces
+ * Since it's faster for the 'use_only_faces' case.
+ *
*/
void bmo_split_exec(BMesh *bm, BMOperator *op)
{
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index e2ff09669d7..f0796e425fa 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -663,7 +663,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* run the separate arg */
if (!BM_edge_is_boundary(es->e_old)) {
- bmesh_edge_separate(bm, es->e_old, es->l, false);
+ bmesh_kernel_edge_separate(bm, es->e_old, es->l, false);
}
/* calc edge-split info */
@@ -742,7 +742,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* disable touching twice, this _will_ happen if the flags not disabled */
BM_elem_flag_disable(v, BM_ELEM_TAG);
- bmesh_vert_separate(bm, v, &vout, &r_vout_len, false);
+ bmesh_kernel_vert_separate(bm, v, &vout, &r_vout_len, false);
v = NULL; /* don't use again */
/* in some cases the edge doesn't split off */
diff --git a/source/blender/bmesh/operators/bmo_offset_edgeloops.c b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
index 7a6f779b34f..a9840a72fc9 100644
--- a/source/blender/bmesh/operators/bmo_offset_edgeloops.c
+++ b/source/blender/bmesh/operators/bmo_offset_edgeloops.c
@@ -270,7 +270,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
v_other = BM_edge_other_vert(e, v);
if (BM_elem_index_get(v_other) == -1) {
if (BM_vert_is_edge_pair(v_other)) {
- /* defer bmesh_jekv to avoid looping over data we're removing */
+ /* defer bmesh_kernel_join_edge_kill_vert to avoid looping over data we're removing */
v_other->e = e;
STACK_PUSH(varr, v_other);
}
@@ -278,7 +278,7 @@ void bmo_offset_edgeloops_exec(BMesh *bm, BMOperator *op)
}
while ((v = STACK_POP(varr))) {
- bmesh_jekv(bm, v->e, v, true, false, false);
+ bmesh_kernel_join_edge_kill_vert(bm, v->e, v, true, false, false);
}
}
}
diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c
index 8408169d85e..723e0b168e0 100644
--- a/source/blender/bmesh/operators/bmo_primitive.c
+++ b/source/blender/bmesh/operators/bmo_primitive.c
@@ -1122,7 +1122,7 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
}
/* Shift borderline coordinates to the left. */
- if (fabsf(theta - M_PI) < 0.0001f) {
+ if (fabsf(theta - (float)M_PI) < 0.0001f) {
theta = -M_PI;
}
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c
index 51b92a3c45e..828c50c39fd 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.c
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c
@@ -110,7 +110,7 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v)
}
-static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center)
+static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new)
{
/* unlikely more than 2 verts are needed */
const unsigned int f_len_orig = (unsigned int)f->len;
@@ -154,10 +154,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
/* common case, just cut the face once */
BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true);
if (l_new) {
- if (oflag_center) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center);
- BMO_face_flag_enable(bm, l_new->f, oflag_center);
- BMO_face_flag_enable(bm, f, oflag_center);
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
}
}
}
@@ -269,10 +270,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con
f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true);
if (l_new) {
- if (oflag_center) {
- BMO_edge_flag_enable(bm, l_new->e, oflag_center);
- BMO_face_flag_enable(bm, l_new->f, oflag_center);
- BMO_face_flag_enable(bm, face_split_arr[j], oflag_center);
+ if (oflag_center | oflag_new) {
+ BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new);
+ }
+ if (oflag_new) {
+ BMO_face_flag_enable(bm, l_new->f, oflag_new);
}
}
@@ -307,7 +309,7 @@ finally:
void BM_mesh_bisect_plane(
BMesh *bm, const float plane[4],
const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps)
+ const short oflag_center, const short oflag_new, const float eps)
{
unsigned int einput_len;
unsigned int i;
@@ -390,7 +392,7 @@ void BM_mesh_bisect_plane(
const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)};
if (side[0] && side[1] && (side[0] != side[1])) {
- const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]);
+ const float e_fac = dist[0] / (dist[0] - dist[1]);
BMVert *v_new;
if (e->l) {
@@ -404,10 +406,17 @@ void BM_mesh_bisect_plane(
} while ((l_iter = l_iter->radial_next) != l_first);
}
- v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac);
+ {
+ BMEdge *e_new;
+ v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac);
+ if (oflag_new) {
+ BMO_edge_flag_enable(bm, e_new, oflag_new);
+ }
+ }
+
vert_is_center_enable(v_new);
- if (oflag_center) {
- BMO_vert_flag_enable(bm, v_new, oflag_center);
+ if (oflag_new | oflag_center) {
+ BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center);
}
BM_VERT_DIR(v_new) = 0;
@@ -448,7 +457,7 @@ void BM_mesh_bisect_plane(
MEM_freeN(edges_arr);
while ((f = BLI_LINKSTACK_POP(face_stack))) {
- bm_face_bisect_verts(bm, f, plane, oflag_center);
+ bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new);
}
/* now we have all faces to split in the stack */
diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h
index 7f3a97c4c79..fb99a1c8214 100644
--- a/source/blender/bmesh/tools/bmesh_bisect_plane.h
+++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h
@@ -30,6 +30,6 @@
void BM_mesh_bisect_plane(
BMesh *bm, const float plane[4],
const bool use_snap_center, const bool use_tag,
- const short oflag_center, const float eps);
+ const short oflag_center, const short oflag_new, const float eps);
#endif /* __BMESH_BISECT_PLANE_H__ */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 2b38af80fc9..87c0f17c937 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -980,7 +980,7 @@ bool BM_mesh_intersect(
struct BMLoop *(*looptris)[3], const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data), void *user_data,
const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
- const int boolean_mode,
+ const bool use_edge_tag, const int boolean_mode,
const float eps)
{
struct ISectState s;
@@ -1516,7 +1516,7 @@ bool BM_mesh_intersect(
BM_mesh_edgesplit(bm, false, true, false);
}
- else if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE) {
+ else if (boolean_mode != BMESH_ISECT_BOOLEAN_NONE || use_edge_tag) {
GSetIterator gs_iter;
/* no need to clear for boolean */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h
index d0cc41654eb..51926a01710 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.h
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -30,7 +30,7 @@ bool BM_mesh_intersect(
struct BMLoop *(*looptris)[3], const int looptris_tot,
int (*test_fn)(BMFace *f, void *user_data), void *user_data,
const bool use_self, const bool use_separate, const bool use_dissolve, const bool use_island_connect,
- const int boolean_mode,
+ const bool use_edge_tag, const int boolean_mode,
const float eps);
enum {
diff --git a/source/blender/bmesh/tools/bmesh_separate.c b/source/blender/bmesh/tools/bmesh_separate.c
new file mode 100644
index 00000000000..ff28ed4c156
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_separate.c
@@ -0,0 +1,133 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/tools/bmesh_separate.c
+ * \ingroup bmesh
+ *
+ * BMesh separate, disconnects a set of faces from all others,
+ * so they don't share any vertices/edges with other faces.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_buffer.h"
+
+#include "bmesh.h"
+#include "intern/bmesh_private.h"
+#include "bmesh_separate.h" /* own include */
+
+/**
+ * Split all faces that match `filter_fn`.
+ * \note
+ */
+void BM_mesh_separate_faces(
+ BMesh *bm,
+ BMFaceFilterFunc filter_fn, void *user_data)
+{
+ BMFace **faces_array_all = MEM_mallocN(bm->totface * sizeof(BMFace *), __func__);
+ /*
+ * - Create an array of faces based on 'filter_fn'.
+ * First part of array for match, for non-match.
+ *
+ * - Enable all vertex tags, then clear all tagged vertices from 'faces_b'.
+ *
+ * - Loop over 'faces_a', checking each vertex,
+ * splitting out any which aren't tagged (and therefor shared), disabling tags as we go.
+ */
+
+ BMFace *f;
+ BMIter iter;
+
+ unsigned int faces_a_len = 0;
+ unsigned int faces_b_len = 0;
+ {
+ int i_a = 0;
+ int i_b = bm->totface;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ faces_array_all[filter_fn(f, user_data) ? i_a++ : --i_b] = f;
+ }
+ faces_a_len = i_a;
+ faces_b_len = bm->totface - i_a;
+ }
+
+ BMFace **faces_a = faces_array_all;
+ BMFace **faces_b = faces_array_all + faces_a_len;
+
+ /* Enable for all */
+ BM_mesh_elem_hflag_enable_all(bm, BM_VERT, BM_ELEM_TAG, false);
+
+ /* Disable vert tag on faces_b */
+ for (unsigned int i = 0; i < faces_b_len; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(faces_b[i]);
+ do {
+ BM_elem_flag_disable(l_iter->v, BM_ELEM_TAG);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+
+ BLI_buffer_declare_static(BMLoop **, loop_split, 0, 128);
+
+ /* Check shared verts ('faces_a' tag and disable) */
+ for (unsigned int i = 0; i < faces_a_len; i++) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(faces_a[i]);
+ do {
+ if (!BM_elem_flag_test(l_iter->v, BM_ELEM_TAG)) {
+ BMVert *v = l_iter->v;
+ /* Enable, since we may visit this vertex again on other faces */
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+
+ /* We know the vertex is shared, collect all vertices and split them off. */
+
+ /* Fill 'loop_split' */
+ {
+ BMEdge *e_first, *e_iter;
+ e_iter = e_first = l_iter->e;
+ do {
+ if (e_iter->l != NULL) {
+ BMLoop *l_radial_first, *l_radial_iter;
+ l_radial_first = l_radial_iter = e_iter->l;
+ do {
+ if (l_radial_iter->v == v) {
+ if (filter_fn(l_radial_iter->f, user_data)) {
+ BLI_buffer_append(&loop_split, BMLoop *, l_radial_iter);
+ }
+ }
+ } while ((l_radial_iter = l_radial_iter->radial_next) != l_radial_first);
+ }
+ } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+ }
+
+ /* Perform the split */
+ BM_face_loop_separate_multi(bm, loop_split.data, loop_split.count);
+
+ BLI_buffer_empty(&loop_split);
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ BLI_buffer_free(&loop_split);
+
+ MEM_freeN(faces_array_all);
+}
diff --git a/source/blender/editors/space_collections/collections_intern.h b/source/blender/bmesh/tools/bmesh_separate.h
index 866f59659c3..91b2b71c872 100644
--- a/source/blender/editors/space_collections/collections_intern.h
+++ b/source/blender/bmesh/tools/bmesh_separate.h
@@ -18,18 +18,15 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/space_collections/collections_intern.h
- * \ingroup spcollections
- */
-
-#ifndef __COLLECTIONS_INTERN_H__
-#define __COLLECTIONS_INTERN_H__
+#ifndef __BMESH_SEPARATE_H__
+#define __BMESH_SEPARATE_H__
-struct wmKeyConfig;
-
-/* collections_ops.c */
-void collections_operatortypes(void);
-void collections_keymap(struct wmKeyConfig *keyconf);
+/** \file blender/bmesh/tools/bmesh_separate.h
+ * \ingroup bmesh
+ */
-#endif /* __COLLECTIONS_INTERN_H__ */
+void BM_mesh_separate_faces(
+ BMesh *bm,
+ BMFaceFilterFunc filter_fn, void *user_data);
+#endif /* __BMESH_SEPARATE_H__ */
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 3801c9300df..bd47ee0214d 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -1934,7 +1934,7 @@ Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::No
mul_m4_m4m4(mat, ipar, temp);
}
- TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size);
+ bc_decompose(mat, job->loc, NULL, job->quat, job->size);
if (par_job) {
job->parent = par_job;
diff --git a/source/blender/collada/ArmatureExporter.cpp b/source/blender/collada/ArmatureExporter.cpp
index 9c26ba83b44..9348f3b3285 100644
--- a/source/blender/collada/ArmatureExporter.cpp
+++ b/source/blender/collada/ArmatureExporter.cpp
@@ -156,11 +156,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ArmatureExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
// parent_mat is armature-space
void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
SceneExporter *se,
@@ -261,47 +256,59 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
//bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
float mat[4][4];
+ float bone_rest_mat[4][4]; /* derived from bone->arm_mat */
+ float parent_rest_mat[4][4]; /* derived from bone->parent->arm_mat */
- if (bone->parent) {
- // get bone-space matrix from parent pose
- /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
- float invpar[4][4];
- invert_m4_m4(invpar, parchan->pose_mat);
- mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
-
- float invpar[4][4];
- invert_m4_m4(invpar, bone->parent->arm_mat);
- mul_m4_m4m4(mat, invpar, bone->arm_mat);
+ bool has_restmat = bc_get_property_matrix(bone, "rest_mat", mat);
- }
- else {
+ if (!has_restmat) {
+
+ /* Have no restpose matrix stored, try old style <= Blender 2.78 */
- //copy_m4_m4(mat, pchan->pose_mat);
- //pose mat is object space
- //New change: export bone->arm_mat
- copy_m4_m4(mat, bone->arm_mat);
- }
+ bc_create_restpose_mat(this->export_settings, bone, bone_rest_mat, bone->arm_mat, true);
- // OPEN_SIM_COMPATIBILITY
- if (export_settings->open_sim) {
- // Remove rotations vs armature from transform
- // parent_rest_rot * mat * irest_rot
- float temp[4][4];
- copy_m4_m4(temp, bone->arm_mat);
- temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
- invert_m4(temp);
+ if (bone->parent) {
+ // get bone-space matrix from parent pose
+ /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
+ float invpar[4][4];
+ invert_m4_m4(invpar, parchan->pose_mat);
+ mul_m4_m4m4(mat, invpar, pchan->pose_mat);*/
+ float invpar[4][4];
+ bc_create_restpose_mat(this->export_settings, bone->parent, parent_rest_mat, bone->parent->arm_mat, true);
- mul_m4_m4m4(mat, mat, temp);
+ invert_m4_m4(invpar, parent_rest_mat);
+ mul_m4_m4m4(mat, invpar, bone_rest_mat);
- if (bone->parent) {
- copy_m4_m4(temp, bone->parent->arm_mat);
+ }
+ else {
+ copy_m4_m4(mat, bone_rest_mat);
+ }
+
+ // OPEN_SIM_COMPATIBILITY
+ if (export_settings->open_sim) {
+ // Remove rotations vs armature from transform
+ // parent_rest_rot * mat * irest_rot
+ float temp[4][4];
+ copy_m4_m4(temp, bone_rest_mat);
temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+ invert_m4(temp);
+
+ mul_m4_m4m4(mat, mat, temp);
- mul_m4_m4m4(mat, temp, mat);
+ if (bone->parent) {
+ copy_m4_m4(temp, parent_rest_mat);
+ temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+
+ mul_m4_m4m4(mat, temp, mat);
+ }
}
}
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(mat, 6);
+
TransformWriter::add_node_transform(node, mat, NULL);
+
}
std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
diff --git a/source/blender/collada/ArmatureExporter.h b/source/blender/collada/ArmatureExporter.h
index 883a6aca847..d271b505aa9 100644
--- a/source/blender/collada/ArmatureExporter.h
+++ b/source/blender/collada/ArmatureExporter.h
@@ -83,8 +83,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
// Scene, SceneExporter and the list of child_objects
// are required for writing bone parented objects
void add_bone_node(Bone *bone, Object *ob_arm, Scene *sce, SceneExporter *se,
diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp
index 17334ca326c..0ea8324ed7c 100644
--- a/source/blender/collada/ArmatureImporter.cpp
+++ b/source/blender/collada/ArmatureImporter.cpp
@@ -32,6 +32,7 @@
#include "COLLADAFWUniqueId.h"
+extern "C" {
#include "BKE_action.h"
#include "BKE_depsgraph.h"
#include "BKE_object.h"
@@ -39,7 +40,9 @@
#include "BLI_string.h"
#include "BLI_listbase.h"
#include "ED_armature.h"
+}
+#include "collada_utils.h"
#include "ArmatureImporter.h"
// use node name, or fall back to original id if not present (name is optional)
@@ -91,6 +94,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
{
float mat[4][4];
float joint_inv_bind_mat[4][4];
+ float joint_bind_mat[4][4];
int chain_length = 0;
//Checking if bone is already made.
@@ -106,7 +110,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
*/
std::map<COLLADAFW::UniqueId, SkinInfo>::iterator skin_it;
- bool bone_is_not_skinned = true;
+ bool bone_is_skinned = false;
for (skin_it = skin_by_data_uid.begin(); skin_it != skin_by_data_uid.end(); skin_it++) {
SkinInfo *b = &skin_it->second;
@@ -114,7 +118,7 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
// get original world-space matrix
invert_m4_m4(mat, joint_inv_bind_mat);
-
+ copy_m4_m4(joint_bind_mat, mat);
// And make local to armature
Object *ob_arm = skin->BKE_armature_from_object();
if (ob_arm) {
@@ -123,24 +127,14 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
mul_m4_m4m4(mat, invmat, mat);
}
- bone_is_not_skinned = false;
+ bone_is_skinned = true;
break;
}
}
// create a bone even if there's no joint data for it (i.e. it has no influence)
- if (bone_is_not_skinned) {
- float obmat[4][4];
- // bone-space
- get_node_mat(obmat, node, NULL, NULL);
-
- // get world-space
- if (parent) {
- mul_m4_m4m4(mat, parent_mat, obmat);
- }
- else {
- copy_m4_m4(mat, obmat);
- }
+ if (!bone_is_skinned) {
+ get_node_mat(mat, node, NULL, NULL, parent_mat);
}
if (parent) bone->parent = parent;
@@ -156,10 +150,11 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
int use_connect = be.get_use_connect();
switch (use_connect) {
- case 1: bone->flag |= BONE_CONNECTED;
- break;
- case 0: bone->flag &= ~BONE_CONNECTED;
- case -1: break; // not defined
+ case 1: bone->flag |= BONE_CONNECTED;
+ break;
+ case -1:/* Connect type not specified */
+ case 0: bone->flag &= ~BONE_CONNECTED;
+ break;
}
if (be.has_roll()) {
@@ -172,6 +167,15 @@ int ArmatureImporter::create_bone(SkinInfo *skin, COLLADAFW::Node *node, EditBon
bone->roll = angle;
}
copy_v3_v3(bone->head, mat[3]);
+
+ if (bone_is_skinned)
+ {
+ float rest_mat[4][4];
+ get_node_mat(rest_mat, node, NULL, NULL, NULL);
+ bc_set_IDPropertyMatrix(bone, "bind_mat", joint_bind_mat);
+ bc_set_IDPropertyMatrix(bone, "rest_mat", rest_mat);
+ }
+
add_v3_v3v3(bone->tail, bone->head, tail); //tail must be non zero
/* find smallest bone length in armature (used later for leaf bone length) */
@@ -273,7 +277,6 @@ void ArmatureImporter::fix_parent_connect(bArmature *armature, Bone *bone)
}
-
void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone, int clip)
{
BoneExtensionMap &extended_bones = bone_extension_manager.getExtensionMap(armature);
@@ -289,12 +292,13 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
for (; child; child = child->next) {
BoneExtended *be = extended_bones[child->name];
if (be != NULL) {
- if (be->get_chain_length() <= clip) {
- if (be->get_chain_length() > maxlen) {
+ int chain_len = be->get_chain_length();
+ if (chain_len <= clip) {
+ if (chain_len > maxlen) {
dominant_child = be;
- maxlen = be->get_chain_length();
+ maxlen = chain_len;
}
- else if (be->get_chain_length() == maxlen) {
+ else if (chain_len == maxlen) {
dominant_child = NULL;
}
}
@@ -308,7 +312,6 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
EditBone *pebone = bc_get_edit_bone(armature, parentbone->name);
EditBone *cebone = bc_get_edit_bone(armature, dominant_child->get_name());
if (pebone && !(cebone->flag & BONE_CONNECTED)) {
-
float vec[3];
sub_v3_v3v3(vec, cebone->head, pebone->head);
@@ -321,14 +324,16 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone
if (len_squared_v3(vec) > MINIMUM_BONE_LENGTH)
{
- pebone->tail[0] = cebone->head[0];
- pebone->tail[1] = cebone->head[1];
- pebone->tail[2] = cebone->head[2];
-
+ copy_v3_v3(pebone->tail, cebone->head);
+ pbe->set_tail(pebone->tail); /* to make fix_leafbone happy ...*/
if (pbe && pbe->get_chain_length() >= this->import_settings->min_chain_length) {
+
+ BoneExtended *cbe = extended_bones[cebone->name];
+ cbe->set_use_connect(true);
+
cebone->flag |= BONE_CONNECTED;
- printf("Connecting chain: parent %s --> %s (child)\n", pebone->name, cebone->name);
pbe->set_leaf_bone(false);
+ printf("Connect Bone chain: parent (%s --> %s) child)\n", pebone->name, cebone->name);
}
}
}
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
index 06e151c363b..1c2642e8313 100644
--- a/source/blender/collada/ControllerExporter.cpp
+++ b/source/blender/collada/ControllerExporter.cpp
@@ -157,11 +157,6 @@ void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<O
}
#endif
-std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm)
-{
- return get_joint_id(bone, ob_arm);
-}
-
std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
{
return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
@@ -468,81 +463,6 @@ std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defb
return source_id;
}
-static float get_property(Bone *bone, const char *key, float def)
-{
- float result = def;
- if (bone->prop) {
- IDProperty *property = IDP_GetPropertyFromGroup(bone->prop, key);
- if (property) {
- switch (property->type) {
- case IDP_INT:
- result = (float)(IDP_Int(property));
- break;
- case IDP_FLOAT:
- result = (float)(IDP_Float(property));
- break;
- case IDP_DOUBLE:
- result = (float)(IDP_Double(property));
- break;
- default:
- result = def;
- }
- }
- }
- return result;
-}
-
-/**
- * This function creates an arbitrary rest pose matrix from
- * data provided as custom properties. This is a workaround
- * for support of maya's restpose matrix which can be arbitrary
- * in opposition to Blender where the Rest pose Matrix is always
- * the Identity matrix.
- *
- * The custom properties are:
- *
- * restpose_scale_x
- * restpose_scale_y
- * restpose_scale_z
- *
- * restpose_rot_x
- * restpose_rot_y
- * restpose_rot_z
- *
- * restpose_loc_x
- * restpose_loc_y
- * restpose_loc_z
- *
- * The matrix is only setup if the scale AND the rot properties are defined.
- * The presence of the loc properties is optional.
- *
- * This feature has been implemented to support Second Life "Fitted Mesh"
- * TODO: Check if an arbitrary rest pose matrix makes sense within Blender.
- * Eventually leverage the custom property data into an "official"
- * Edit_bone Property
- */
-static void create_restpose_mat(Bone *bone, float mat[4][4])
-{
- float loc[3] = {
- get_property(bone, "restpose_loc_x", 0.0),
- get_property(bone, "restpose_loc_y", 0.0),
- get_property(bone, "restpose_loc_z", 0.0)
- };
-
- float rot[3] = {
- DEG2RADF(get_property(bone, "restpose_rot_x", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_y", 0.0)),
- DEG2RADF(get_property(bone, "restpose_rot_z", 0.0))
- };
-
- float scale[3] = {
- get_property(bone, "restpose_scale_x", 1.0),
- get_property(bone, "restpose_scale_y", 1.0),
- get_property(bone, "restpose_scale_z", 1.0)
- };
-
- loc_eulO_size_to_mat4(mat, loc, rot, scale, 6);
-}
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
{
@@ -585,30 +505,36 @@ std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBas
float world[4][4];
float inv_bind_mat[4][4];
+ float bind_mat[4][4]; /* derived from bone->arm_mat */
+
+ bool has_bindmat = bc_get_property_matrix(pchan->bone, "bind_mat", bind_mat);
- // SL/OPEN_SIM COMPATIBILITY
- if (export_settings->open_sim) {
- // Only translations, no rotation vs armature
- float temp[4][4];
- unit_m4(temp);
- copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
- mul_m4_m4m4(world, ob_arm->obmat, temp);
-
- // Add Maya restpose matrix (if defined as properties)
- float restpose_mat[4][4];
- create_restpose_mat(pchan->bone, restpose_mat);
- mul_m4_m4m4(world, world, restpose_mat);
+ if (!has_bindmat) {
- }
- else {
- // make world-space matrix, arm_mat is armature-space
- mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
+ /* Have no bind matrix stored, try old style <= Blender 2.78 */
+
+ bc_create_restpose_mat(this->export_settings, pchan->bone, bind_mat, pchan->bone->arm_mat, true);
+
+ // SL/OPEN_SIM COMPATIBILITY
+ if (export_settings->open_sim) {
+
+ float loc[3];
+ float rot[3] = { 0, 0, 0 };
+ float scale[3];
+ bc_decompose(bind_mat, loc, NULL, NULL, scale);
+
+ // Only translations, no rotation vs armature
+ loc_eulO_size_to_mat4(bind_mat, loc, rot, scale, 6);
+ }
}
+ // make world-space matrix (bind_mat is armature-space)
+ mul_m4_m4m4(world, ob_arm->obmat, bind_mat);
invert_m4_m4(mat, world);
converter.mat4_to_dae(inv_bind_mat, mat);
-
+ if (this->export_settings->limit_precision)
+ bc_sanitize_mat(inv_bind_mat, 6);
source.appendValues(inv_bind_mat);
}
}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 0be51187f6f..80b858ca6dd 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -84,8 +84,6 @@ private:
void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
#endif
- std::string get_joint_sid(Bone *bone, Object *ob_arm);
-
std::string get_controller_id(Object *ob_arm, Object *ob);
std::string get_controller_id(Key *key, Object *ob);
diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h
index 9451cac9dae..de91f68a492 100644
--- a/source/blender/collada/ExportSettings.h
+++ b/source/blender/collada/ExportSettings.h
@@ -51,7 +51,10 @@ public:
bool use_blender_profile;
bool sort_by_name;
BC_export_transformation_type export_transformation_type;
+
bool open_sim;
+ bool limit_precision;
+ bool keep_bind_info;
char *filepath;
LinkNode *export_set;
diff --git a/source/blender/collada/ImportSettings.h b/source/blender/collada/ImportSettings.h
index 2c52d73e756..4a2d4e8046a 100644
--- a/source/blender/collada/ImportSettings.h
+++ b/source/blender/collada/ImportSettings.h
@@ -37,6 +37,7 @@ public:
bool fix_orientation;
int min_chain_length;
char *filepath;
+ bool keep_bind_info;
};
#endif
diff --git a/source/blender/collada/SkinInfo.cpp b/source/blender/collada/SkinInfo.cpp
index 7242a24523c..71875d6274a 100644
--- a/source/blender/collada/SkinInfo.cpp
+++ b/source/blender/collada/SkinInfo.cpp
@@ -230,7 +230,6 @@ 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);
diff --git a/source/blender/collada/TransformReader.cpp b/source/blender/collada/TransformReader.cpp
index f8f31304d28..7f742be7e30 100644
--- a/source/blender/collada/TransformReader.cpp
+++ b/source/blender/collada/TransformReader.cpp
@@ -34,7 +34,21 @@ TransformReader::TransformReader(UnitConverter *conv) : unit_converter(conv)
/* pass */
}
-void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob)
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob)
+{
+ get_node_mat(mat, node, animation_map, ob, NULL);
+}
+
+void TransformReader::get_node_mat(
+ float mat[4][4],
+ COLLADAFW::Node *node,
+ std::map<COLLADAFW::UniqueId, Animation> *animation_map,
+ Object *ob,
+ float parent_mat[4][4])
{
float cur[4][4];
float copy[4][4];
@@ -52,6 +66,9 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
// then this is considered as redundant information.
// So if we find a Matrix we use that and return.
dae_matrix_to_mat4(tm, mat);
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
return;
case COLLADAFW::Transformation::TRANSLATE:
dae_translate_to_mat4(tm, cur);
@@ -80,6 +97,10 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
(*animation_map)[anim_list_id] = anim;
}
}
+
+ if (parent_mat) {
+ mul_m4_m4m4(mat, parent_mat, mat);
+ }
}
void TransformReader::dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4])
diff --git a/source/blender/collada/TransformReader.h b/source/blender/collada/TransformReader.h
index ab974b9ba85..08bb17ccac1 100644
--- a/source/blender/collada/TransformReader.h
+++ b/source/blender/collada/TransformReader.h
@@ -43,7 +43,7 @@
//struct Object;
-class TransformReader : public TransformBase
+class TransformReader
{
protected:
@@ -59,7 +59,8 @@ public:
TransformReader(UnitConverter *conv);
void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob);
-
+ void get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, Animation> *animation_map, Object *ob, float parent_mat[4][4]);
+
void dae_rotate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_translate_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
void dae_scale_to_mat4(COLLADAFW::Transformation *tm, float m[4][4]);
diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp
index 908111ebae6..b7eeff3b074 100644
--- a/source/blender/collada/TransformWriter.cpp
+++ b/source/blender/collada/TransformWriter.cpp
@@ -27,11 +27,10 @@
#include "BKE_object.h"
+#include "BLI_math.h"
#include "TransformWriter.h"
-#include "BLI_math.h"
-
void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4])
{
float loc[3], rot[3], scale[3];
@@ -51,7 +50,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
converter->mat4_to_dae_double(dmat, local);
delete converter;
- TransformBase::decompose(local, loc, rot, NULL, scale);
+ bc_decompose(local, loc, rot, NULL, scale);
if (node.getType() == COLLADASW::Node::JOINT) {
// XXX Why are joints handled differently ?
@@ -116,7 +115,7 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, B
case BC_TRANSFORMATION_TYPE_TRANSROTLOC:
{
float loc[3], rot[3], scale[3];
- TransformBase::decompose(f_obmat, loc, rot, NULL, scale);
+ bc_decompose(f_obmat, loc, rot, NULL, scale);
add_transform(node, loc, rot, scale);
break;
}
diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h
index 7f69a4b9c95..5bb13d4aac9 100644
--- a/source/blender/collada/TransformWriter.h
+++ b/source/blender/collada/TransformWriter.h
@@ -33,9 +33,10 @@
#include "DNA_object_types.h"
#include "collada_internal.h"
+#include "collada_utils.h"
#include "collada.h"
-class TransformWriter : protected TransformBase
+class TransformWriter
{
protected:
void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]);
diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp
index fe8b1d2320a..25673cae9d6 100644
--- a/source/blender/collada/collada.cpp
+++ b/source/blender/collada/collada.cpp
@@ -48,7 +48,8 @@ int collada_import(bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length)
+ int min_chain_length,
+ int keep_bind_info)
{
ImportSettings import_settings;
@@ -58,6 +59,7 @@ int collada_import(bContext *C,
import_settings.find_chains = find_chains != 0;
import_settings.fix_orientation = fix_orientation != 0;
import_settings.min_chain_length = min_chain_length;
+ import_settings.keep_bind_info = keep_bind_info !=0;
DocumentImporter imp(C, &import_settings);
if (imp.import()) return 1;
@@ -66,6 +68,7 @@ int collada_import(bContext *C,
}
int collada_export(Scene *sce,
+ SceneLayer *scene_layer,
const char *filepath,
int apply_modifiers,
@@ -87,7 +90,9 @@ int collada_export(Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim)
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info)
{
ExportSettings export_settings;
@@ -112,14 +117,15 @@ int collada_export(Scene *sce,
export_settings.sort_by_name = sort_by_name != 0;
export_settings.export_transformation_type = export_transformation_type;
export_settings.open_sim = open_sim != 0;
-
+ export_settings.limit_precision = limit_precision != 0;
+ export_settings.keep_bind_info = keep_bind_info !=0;
int includeFilter = OB_REL_NONE;
if (export_settings.include_armatures) includeFilter |= OB_REL_MOD_ARMATURE;
if (export_settings.include_children) includeFilter |= OB_REL_CHILDREN_RECURSIVE;
eObjectSet objectSet = (export_settings.selected) ? OB_SET_SELECTED : OB_SET_ALL;
- export_settings.export_set = BKE_object_relational_superset(sce, objectSet, (eObRelationTypes)includeFilter);
+ export_settings.export_set = BKE_object_relational_superset(scene_layer, objectSet, (eObRelationTypes)includeFilter);
int export_count = BLI_linklist_count(export_settings.export_set);
if (export_count == 0) {
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index a4416608584..c8e6c99206a 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -48,6 +48,7 @@ typedef enum BC_export_transformation_type {
struct bContext;
struct Scene;
+struct SceneLayer;
/*
* both return 1 on success, 0 on error
@@ -58,9 +59,12 @@ int collada_import(struct bContext *C,
int find_chains,
int auto_connect,
int fix_orientation,
- int min_chain_length);
+ int min_chain_length,
+
+ int keep_bind_info);
int collada_export(struct Scene *sce,
+ struct SceneLayer *scene_layer,
const char *filepath,
int apply_modifiers,
BC_export_mesh_type export_mesh_type,
@@ -81,9 +85,10 @@ int collada_export(struct Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim);
-
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info);
#ifdef __cplusplus
}
diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp
index e1a13559b08..6ebde6bd773 100644
--- a/source/blender/collada/collada_internal.cpp
+++ b/source/blender/collada/collada_internal.cpp
@@ -162,18 +162,6 @@ void UnitConverter::calculate_scale(Scene &sce)
size_to_mat4(scale_mat4, rescale);
}
-void TransformBase::decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
-{
- mat4_to_size(size, mat);
- if (eul) {
- mat4_to_eul(eul, mat);
- }
- if (quat) {
- mat4_to_quat(quat, mat);
- }
- copy_v3_v3(loc, mat[3]);
-}
-
/**
* Translation map.
* Used to translate every COLLADA id to a valid id, no matter what "wrong" letters may be
@@ -341,7 +329,12 @@ std::string get_light_id(Object *ob)
std::string get_joint_id(Bone *bone, Object *ob_arm)
{
- return translate_id(/*id_name(ob_arm) + "_" +*/ bone->name);
+ return translate_id(id_name(ob_arm) + "_" + bone->name);
+}
+
+std::string get_joint_sid(Bone *bone, Object *ob_arm)
+{
+ return translate_id(bone->name);
}
std::string get_camera_id(Object *ob)
diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h
index 4aa637a6876..1c7aa160f57 100644
--- a/source/blender/collada/collada_internal.h
+++ b/source/blender/collada/collada_internal.h
@@ -85,12 +85,6 @@ public:
};
-class TransformBase
-{
-public:
- void decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
-};
-
extern void clear_global_id_map();
/** Look at documentation of translate_map */
extern std::string translate_id(const std::string &id);
@@ -104,6 +98,7 @@ extern std::string get_geometry_id(Object *ob, bool use_instantiation);
extern std::string get_light_id(Object *ob);
extern std::string get_joint_id(Bone *bone, Object *ob_arm);
+extern std::string get_joint_sid(Bone *bone, Object *ob_arm);
extern std::string get_camera_id(Object *ob);
diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp
index 2efa8b21d81..ac4395e1430 100644
--- a/source/blender/collada/collada_utils.cpp
+++ b/source/blender/collada/collada_utils.cpp
@@ -32,8 +32,6 @@
#include "COLLADAFWMeshPrimitive.h"
#include "COLLADAFWMeshVertexData.h"
-#include "collada_utils.h"
-
extern "C" {
#include "DNA_modifier_types.h"
#include "DNA_customdata_types.h"
@@ -63,6 +61,9 @@ extern "C" {
#include "bmesh_tools.h"
}
+#include "collada_utils.h"
+#include "ExportSettings.h"
+
float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index)
{
if (index >= array.getValuesCount())
@@ -352,6 +353,28 @@ void bc_match_scale(std::vector<Object *> *objects_done,
}
}
+/*
+ Convenience function to get only the needed components of a matrix
+*/
+void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size)
+{
+ if (size) {
+ mat4_to_size(size, mat);
+ }
+
+ if (eul) {
+ mat4_to_eul(eul, mat);
+ }
+
+ if (quat) {
+ mat4_to_quat(quat, mat);
+ }
+
+ if (loc) {
+ copy_v3_v3(loc, mat[3]);
+ }
+}
+
void bc_triangulate_mesh(Mesh *me)
{
bool use_beauty = false;
@@ -612,3 +635,200 @@ int BoneExtended::get_use_connect()
{
return this->use_connect;
}
+
+/**
+* Stores a 4*4 matrix as a custom bone property array of size 16
+*/
+void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4])
+{
+ IDProperty *idgroup = (IDProperty *)ebone->prop;
+ if (idgroup == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ idgroup = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ ebone->prop = idgroup;
+ }
+
+ IDPropertyTemplate val = { 0 };
+ val.array.len = 16;
+ val.array.type = IDP_FLOAT;
+
+ IDProperty *data = IDP_New(IDP_ARRAY, &val, key);
+ float *array = (float *)IDP_Array(data);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ array[4 * i + j] = mat[i][j];
+
+ IDP_AddToGroup(idgroup, data);
+}
+
+#if 0
+/**
+* Stores a Float value as a custom bone property
+*
+* Note: This function is currently not needed. Keep for future usage
+*/
+static void bc_set_IDProperty(EditBone *ebone, const char *key, float value)
+{
+ if (ebone->prop == NULL)
+ {
+ IDPropertyTemplate val = { 0 };
+ ebone->prop = IDP_New(IDP_GROUP, &val, "RNA_EditBone ID properties");
+ }
+
+ IDProperty *pgroup = (IDProperty *)ebone->prop;
+ IDPropertyTemplate val = { 0 };
+ IDProperty *prop = IDP_New(IDP_FLOAT, &val, key);
+ IDP_Float(prop) = value;
+ IDP_AddToGroup(pgroup, prop);
+
+}
+#endif
+
+/*
+* Get a custom property when it exists.
+* This function is also used to check if a property exists.
+*/
+IDProperty *bc_get_IDProperty(Bone *bone, std::string key)
+{
+ return (bone->prop == NULL) ? NULL : IDP_GetPropertyFromGroup(bone->prop, key.c_str());
+}
+
+/**
+* Read a custom bone property and convert to float
+* Return def if the property does not exist.
+*/
+float bc_get_property(Bone *bone, std::string key, float def)
+{
+ float result = def;
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property) {
+ switch (property->type) {
+ case IDP_INT:
+ result = (float)(IDP_Int(property));
+ break;
+ case IDP_FLOAT:
+ result = (float)(IDP_Float(property));
+ break;
+ case IDP_DOUBLE:
+ result = (float)(IDP_Double(property));
+ break;
+ default:
+ result = def;
+ }
+ }
+ return result;
+}
+
+/**
+* Read a custom bone property and convert to matrix
+* Return true if conversion was succesfull
+*
+* Return false if:
+* - the property does not exist
+* - is not an array of size 16
+*/
+bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4])
+{
+ IDProperty *property = bc_get_IDProperty(bone, key);
+ if (property && property->type == IDP_ARRAY && property->len == 16) {
+ float *array = (float *)IDP_Array(property);
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = array[4 * i + j];
+ return true;
+ }
+ return false;
+}
+
+/**
+* get a vector that is stored in 3 custom properties (used in Blender <= 2.78)
+*/
+void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3])
+{
+ val[0] = bc_get_property(bone, key + "_x", def[0]);
+ val[1] = bc_get_property(bone, key + "_y", def[1]);
+ val[2] = bc_get_property(bone, key + "_z", def[2]);
+}
+
+/**
+* Check if vector exist stored in 3 custom properties (used in Blender <= 2.78)
+*/
+static bool has_custom_props(Bone *bone, bool enabled, std::string key)
+{
+ if (!enabled)
+ return false;
+
+ return (bc_get_IDProperty(bone, key + "_x")
+ || bc_get_IDProperty(bone, key + "_y")
+ || bc_get_IDProperty(bone, key + "_z"));
+
+}
+
+/**
+* Check if custom information about bind matrix exists and modify the from_mat
+* accordingly.
+*
+* Note: This is old style for Blender <= 2.78 only kept for compatibility
+*/
+void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float from_mat[4][4], bool use_local_space)
+{
+ float loc[3];
+ float rot[3];
+ float scale[3];
+ static const float V0[3] = { 0, 0, 0 };
+
+ if (!has_custom_props(bone, export_settings->keep_bind_info, "restpose_loc") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_rot") &&
+ !has_custom_props(bone, export_settings->keep_bind_info, "restpose_scale"))
+ {
+ /* No need */
+ copy_m4_m4(to_mat, from_mat);
+ return;
+ }
+
+ bc_decompose(from_mat, loc, rot, NULL, scale);
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_loc", loc, loc);
+
+ if (use_local_space && bone->parent) {
+ Bone *b = bone;
+ while (b->parent) {
+ b = b->parent;
+ float ploc[3];
+ bc_get_property_vector(b, "restpose_loc", ploc, V0);
+ loc[0] += ploc[0];
+ loc[1] += ploc[1];
+ loc[2] += ploc[2];
+ }
+ }
+ }
+
+ if (export_settings->keep_bind_info) {
+ if (bc_get_IDProperty(bone, "restpose_rot_x"))
+ rot[0] = DEG2RADF(bc_get_property(bone, "restpose_rot_x", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_y"))
+ rot[1] = DEG2RADF(bc_get_property(bone, "restpose_rot_y", 0));
+ if (bc_get_IDProperty(bone, "restpose_rot_z"))
+ rot[2] = DEG2RADF(bc_get_property(bone, "restpose_rot_z", 0));
+ }
+
+ if (export_settings->keep_bind_info) {
+ bc_get_property_vector(bone, "restpose_scale", scale, scale);
+ }
+
+ loc_eulO_size_to_mat4(to_mat, loc, rot, scale, 6);
+
+}
+
+/*
+ Make 4*4 matrices better readable
+*/
+void bc_sanitize_mat(float mat[4][4], int precision)
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ mat[i][j] = double_round(mat[i][j], precision);
+} \ No newline at end of file
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index 7fdbef3b6cb..38c0bd5096a 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -53,8 +53,10 @@ extern "C" {
#include "BKE_object.h"
#include "BKE_DerivedMesh.h"
#include "BKE_scene.h"
+#include "BKE_idprop.h"
}
+#include "ImportSettings.h"
#include "ExportSettings.h"
#include "collada_internal.h"
@@ -88,11 +90,24 @@ extern std::string bc_url_encode(std::string data);
extern void bc_match_scale(Object *ob, UnitConverter &bc_unit, bool scale_to_scene);
extern void bc_match_scale(std::vector<Object *> *objects_done, UnitConverter &unit_converter, bool scale_to_scene);
+extern void bc_decompose(float mat[4][4], float *loc, float eul[3], float quat[4], float *size);
+
extern void bc_triangulate_mesh(Mesh *me);
extern bool bc_is_leaf_bone(Bone *bone);
extern EditBone *bc_get_edit_bone(bArmature * armature, char *name);
extern int bc_set_layer(int bitfield, int layer, bool enable);
extern int bc_set_layer(int bitfield, int layer);
+extern void bc_sanitize_mat(float mat[4][4], int precision);
+
+extern IDProperty *bc_get_IDProperty(Bone *bone, std::string key);
+extern void bc_set_IDProperty(EditBone *ebone, const char *key, float value);
+extern void bc_set_IDPropertyMatrix(EditBone *ebone, const char *key, float mat[4][4]);
+
+extern float bc_get_property(Bone *bone, std::string key, float def);
+extern void bc_get_property_vector(Bone *bone, std::string key, float val[3], const float def[3]);
+extern bool bc_get_property_matrix(Bone *bone, std::string key, float mat[4][4]);
+
+extern void bc_create_restpose_mat(const ExportSettings *export_settings, Bone *bone, float to_mat[4][4], float world[4][4], bool use_local_space);
class BCPolygonNormalsIndices
{
diff --git a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
index e1ada9a8c39..5f78067220a 100644
--- a/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionEdgeFilterOperation.cpp
@@ -94,4 +94,10 @@ void ConvolutionEdgeFilterOperation::executePixel(float output[4], int x, int y,
output[2] = output[2] * value[0] + in2[2] * mval;
output[3] = in2[3];
+
+ /* Make sure we don't return negative color. */
+ output[0] = max(output[0], 0.0f);
+ output[1] = max(output[1], 0.0f);
+ output[2] = max(output[2], 0.0f);
+ output[3] = max(output[3], 0.0f);
}
diff --git a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
index 68ec2be5ebd..6ac1ff9a1eb 100644
--- a/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
+++ b/source/blender/compositor/operations/COM_ConvolutionFilterOperation.cpp
@@ -107,6 +107,12 @@ void ConvolutionFilterOperation::executePixel(float output[4], int x, int y, voi
output[1] = output[1] * value[0] + in2[1] * mval;
output[2] = output[2] * value[0] + in2[2] * mval;
output[3] = output[3] * value[0] + in2[3] * mval;
+
+ /* Make sure we don't return negative color. */
+ output[0] = max(output[0], 0.0f);
+ output[1] = max(output[1], 0.0f);
+ output[2] = max(output[2], 0.0f);
+ output[3] = max(output[3], 0.0f);
}
bool ConvolutionFilterOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
index 957ac5af748..57aa3a1bac2 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
@@ -44,18 +44,18 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil
xp = x + i;
tbuf1->read(c, x, y);
mul_v3_fl(c, f1);
- tbuf1->read(tc, (settings->angle ? xm : x), ym);
+ tbuf1->read(tc, (settings->star_45 ? xm : x), ym);
madd_v3_v3fl(c, tc, f2);
- tbuf1->read(tc, (settings->angle ? xp : x), yp);
+ tbuf1->read(tc, (settings->star_45 ? xp : x), yp);
madd_v3_v3fl(c, tc, f2);
c[3] = 1.0f;
tbuf1->writePixel(x, y, c);
tbuf2->read(c, x, y);
mul_v3_fl(c, f1);
- tbuf2->read(tc, xm, (settings->angle ? yp : y));
+ tbuf2->read(tc, xm, (settings->star_45 ? yp : y));
madd_v3_v3fl(c, tc, f2);
- tbuf2->read(tc, xp, (settings->angle ? ym : y));
+ tbuf2->read(tc, xp, (settings->star_45 ? ym : y));
madd_v3_v3fl(c, tc, f2);
c[3] = 1.0f;
tbuf2->writePixel(x, y, c);
@@ -73,18 +73,18 @@ void GlareSimpleStarOperation::generateGlare(float *data, MemoryBuffer *inputTil
xp = x + i;
tbuf1->read(c, x, y);
mul_v3_fl(c, f1);
- tbuf1->read(tc, (settings->angle ? xm : x), ym);
+ tbuf1->read(tc, (settings->star_45 ? xm : x), ym);
madd_v3_v3fl(c, tc, f2);
- tbuf1->read(tc, (settings->angle ? xp : x), yp);
+ tbuf1->read(tc, (settings->star_45 ? xp : x), yp);
madd_v3_v3fl(c, tc, f2);
c[3] = 1.0f;
tbuf1->writePixel(x, y, c);
tbuf2->read(c, x, y);
mul_v3_fl(c, f1);
- tbuf2->read(tc, xm, (settings->angle ? yp : y));
+ tbuf2->read(tc, xm, (settings->star_45 ? yp : y));
madd_v3_v3fl(c, tc, f2);
- tbuf2->read(tc, xp, (settings->angle ? ym : y));
+ tbuf2->read(tc, xp, (settings->star_45 ? ym : y));
madd_v3_v3fl(c, tc, f2);
c[3] = 1.0f;
tbuf2->writePixel(x, y, c);
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
index da6076337b4..535f2952e5d 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
@@ -28,7 +28,7 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile,
int x, y, n;
unsigned int nump = 0;
float c1[4], c2[4], c3[4], c4[4];
- float a, ang = DEG2RADF(360.0f) / (float)settings->angle;
+ float a, ang = DEG2RADF(360.0f) / (float)settings->streaks;
int size = inputTile->getWidth() * inputTile->getHeight();
int size4 = size * 4;
diff --git a/source/blender/depsgraph/CMakeLists.txt b/source/blender/depsgraph/CMakeLists.txt
index 2d32e85bf64..a266f30fe11 100644
--- a/source/blender/depsgraph/CMakeLists.txt
+++ b/source/blender/depsgraph/CMakeLists.txt
@@ -43,11 +43,13 @@ set(SRC
intern/builder/deg_builder.cc
intern/builder/deg_builder_cycle.cc
intern/builder/deg_builder_nodes.cc
+ intern/builder/deg_builder_nodes_layer.cc
intern/builder/deg_builder_nodes_rig.cc
intern/builder/deg_builder_nodes_scene.cc
intern/builder/deg_builder_pchanmap.cc
intern/builder/deg_builder_relations.cc
intern/builder/deg_builder_relations_keys.cc
+ intern/builder/deg_builder_relations_layer.cc
intern/builder/deg_builder_relations_rig.cc
intern/builder/deg_builder_relations_scene.cc
intern/builder/deg_builder_transitive.cc
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index cb2f057a090..828da6cb056 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -77,28 +77,8 @@ static bool check_object_needs_evaluation(Object *object)
return false;
}
-void deg_graph_build_finalize(Depsgraph *graph)
+void deg_graph_build_flush_layers(Depsgraph *graph)
{
- /* STEP 1: Make sure new invisible dependencies are ready for use.
- *
- * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
- * to do it ahead of a time and don't spend time on flushing updates on
- * every frame change.
- */
- GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
- {
- if (id_node->layers == 0) {
- ID *id = id_node->id;
- if (GS(id->name) == ID_OB) {
- Object *object = (Object *)id;
- if (check_object_needs_evaluation(object)) {
- id_node->tag_update(graph);
- }
- }
- }
- }
- GHASH_FOREACH_END();
- /* STEP 2: Flush visibility layers from children to parent. */
std::stack<OperationDepsNode *> stack;
foreach (OperationDepsNode *node, graph->operations) {
IDDepsNode *id_node = node->owner->owner;
@@ -143,6 +123,31 @@ void deg_graph_build_finalize(Depsgraph *graph)
}
}
}
+}
+
+void deg_graph_build_finalize(Depsgraph *graph)
+{
+ /* STEP 1: Make sure new invisible dependencies are ready for use.
+ *
+ * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
+ * to do it ahead of a time and don't spend time on flushing updates on
+ * every frame change.
+ */
+ GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
+ {
+ if (id_node->layers == 0) {
+ ID *id = id_node->id;
+ if (GS(id->name) == ID_OB) {
+ Object *object = (Object *)id;
+ if (check_object_needs_evaluation(object)) {
+ id_node->tag_update(graph);
+ }
+ }
+ }
+ }
+ GHASH_FOREACH_END();
+ /* STEP 2: Flush visibility layers from children to parent. */
+ deg_graph_build_flush_layers(graph);
/* STEP 3: Re-tag IDs for update if it was tagged before the relations
* update tag.
*/
@@ -154,7 +159,7 @@ void deg_graph_build_finalize(Depsgraph *graph)
}
GHASH_FOREACH_END();
- if ((id_node->layers & graph->layers) != 0) {
+ if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) {
ID *id = id_node->id;
if ((id->tag & LIB_TAG_ID_RECALC_ALL) &&
(id->tag & LIB_TAG_DOIT))
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index bdc030e3810..3cc51a2d7db 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -42,5 +42,6 @@ struct Depsgraph;
string deg_fcurve_id_name(const FCurve *fcu);
void deg_graph_build_finalize(struct Depsgraph *graph);
+void deg_graph_build_flush_layers(struct Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
index 0f0d16907f4..b6071b10757 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -433,7 +433,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob)
}
/* Object data. */
- if (ob->data) {
+ if (ob->data != NULL) {
/* type-specific data... */
switch (ob->type) {
case OB_MESH: /* Geometry */
@@ -491,14 +491,25 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Object *ob)
build_animdata(&ob->id);
/* particle systems */
- if (ob->particlesystem.first) {
+ if (ob->particlesystem.first != NULL) {
build_particles(scene, ob);
}
- /* grease pencil */
- if (ob->gpd) {
+ /* Grease pencil. */
+ if (ob->gpd != NULL) {
build_gpencil(ob->gpd);
}
+
+ /* Object that this is a proxy for. */
+ if (ob->proxy) {
+ ob->proxy->proxy_from = ob;
+ build_object(scene, ob->proxy);
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group != NULL) {
+ build_group(scene, ob->dup_group);
+ }
}
void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob)
@@ -735,7 +746,8 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
*/
/* component for all particle systems */
- ComponentDepsNode *psys_comp = add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
+ ComponentDepsNode *psys_comp =
+ add_component_node(&ob->id, DEPSNODE_TYPE_EVAL_PARTICLES);
/* particle systems */
LINKLIST_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
@@ -748,11 +760,12 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
/* this particle system */
// TODO: for now, this will just be a placeholder "ubereval" node
add_operation_node(psys_comp,
- DEPSOP_TYPE_EXEC, function_bind(BKE_particle_system_eval,
- _1,
- scene,
- ob,
- psys),
+ DEPSOP_TYPE_EXEC,
+ function_bind(BKE_particle_system_eval,
+ _1,
+ scene,
+ ob,
+ psys),
DEG_OPCODE_PSYS_EVAL,
psys->name);
}
@@ -761,6 +774,20 @@ void DepsgraphNodeBuilder::build_particles(Scene *scene, Object *ob)
// TODO...
}
+void DepsgraphNodeBuilder::build_cloth(Scene *scene, Object *object)
+{
+ ComponentDepsNode *cache_comp = add_component_node(&object->id,
+ DEPSNODE_TYPE_CACHE);
+ add_operation_node(cache_comp,
+ DEPSOP_TYPE_EXEC,
+ function_bind(BKE_object_eval_cloth,
+ _1,
+ scene,
+ object),
+ DEG_OPCODE_PLACEHOLDER,
+ "Cloth Modifier");
+}
+
/* Shapekeys */
void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
@@ -822,6 +849,9 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
md),
DEG_OPCODE_GEOMETRY_MODIFIER,
md->name);
+ if (md->type == eModifierType_Cloth) {
+ build_cloth(scene, ob);
+ }
}
/* materials */
@@ -835,8 +865,8 @@ void DepsgraphNodeBuilder::build_obdata_geom(Scene *scene, Object *ob)
add_operation_node(&ob->id,
DEPSNODE_TYPE_SHADING,
DEPSOP_TYPE_EXEC,
- function_bind(BKE_object_eval_shading, _1, ob),
- DEG_OPCODE_OPERATION, "Material Update");
+ NULL,
+ DEG_OPCODE_PLACEHOLDER, "Material Update");
}
/* geometry collision */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index 2f3f733b8db..d28aaf6a10a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -41,6 +41,7 @@ struct Image;
struct FCurve;
struct Group;
struct Key;
+struct LayerCollection;
struct Main;
struct Material;
struct Mask;
@@ -132,6 +133,7 @@ struct DepsgraphNodeBuilder {
void build_pose_constraints(Object *ob, bPoseChannel *pchan);
void build_rigidbody(Scene *scene);
void build_particles(Scene *scene, Object *ob);
+ void build_cloth(Scene *scene, Object *object);
void build_animdata(ID *id);
OperationDepsNode *build_driver(ID *id, FCurve *fcurve);
void build_ik_pose(Scene *scene,
@@ -160,6 +162,17 @@ struct DepsgraphNodeBuilder {
void build_mask(Mask *mask);
void build_movieclip(MovieClip *clip);
+ struct LayerCollectionState {
+ int index;
+ LayerCollection *parent;
+ };
+ void build_layer_collection(Scene *scene,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state);
+ void build_layer_collections(Scene *scene,
+ ListBase *layer_collections,
+ LayerCollectionState *state);
+ void build_scene_layer_collections(Scene *scene);
protected:
Main *m_bmain;
Depsgraph *m_graph;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc
new file mode 100644
index 00000000000..494ae585272
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer.cc
@@ -0,0 +1,121 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph's nodes
+ */
+
+#include "intern/builder/deg_builder_nodes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+
+#include "BKE_layer.h"
+
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+#include "intern/depsgraph_types.h"
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphNodeBuilder::build_layer_collection(Scene *scene,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state)
+{
+ /* TODO(sergey): This will attempt to create component for each collection.
+ * Harmless but could be optimized.
+ */
+ ComponentDepsNode *comp = add_component_node(&scene->id, DEPSNODE_TYPE_LAYER_COLLECTIONS);
+
+ add_operation_node(comp,
+ DEPSOP_TYPE_EXEC,
+ function_bind(BKE_layer_eval_layer_collection,
+ _1,
+ scene,
+ layer_collection,
+ state->parent),
+ DEG_OPCODE_SCENE_LAYER_EVAL,
+ layer_collection->scene_collection->name,
+ state->index);
+ ++state->index;
+
+ /* Recurs into nested layer collections. */
+ LayerCollection *parent = state->parent;
+ state->parent = layer_collection;
+ build_layer_collections(scene, &layer_collection->layer_collections, state);
+ state->parent = parent;
+}
+
+void DepsgraphNodeBuilder::build_layer_collections(Scene *scene,
+ ListBase *layer_collections,
+ LayerCollectionState *state)
+{
+ LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
+ build_layer_collection(scene, layer_collection, state);
+ }
+}
+
+void DepsgraphNodeBuilder::build_scene_layer_collections(Scene *scene)
+{
+ LayerCollectionState state;
+ state.index = 0;
+ LINKLIST_FOREACH (SceneLayer *, scene_layer, &scene->render_layers) {
+ ComponentDepsNode *comp = add_component_node(&scene->id, DEPSNODE_TYPE_LAYER_COLLECTIONS);
+
+ add_operation_node(comp,
+ DEPSOP_TYPE_EXEC,
+ function_bind(BKE_layer_eval_layer_collection_pre, _1, scene, scene_layer),
+ DEG_OPCODE_SCENE_LAYER_INIT,
+ scene_layer->name);
+ add_operation_node(comp,
+ DEPSOP_TYPE_EXEC,
+ function_bind(BKE_layer_eval_layer_collection_post, _1, scene_layer),
+ DEG_OPCODE_SCENE_LAYER_DONE,
+ scene_layer->name);
+
+ state.parent = NULL;
+ build_layer_collections(scene, &scene_layer->layer_collections, &state);
+ }
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
index c7e8edb122e..3f9febc1228 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_scene.cc
@@ -80,23 +80,10 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
}
/* scene objects */
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
/* object itself */
build_object(scene, 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, ob->proxy);
- }
-
- /* Object dupligroup. */
- if (ob->dup_group) {
- build_group(scene, ob->dup_group);
- }
}
FOREACH_SCENE_OBJECT_END
@@ -142,6 +129,9 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene)
LINKLIST_FOREACH (MovieClip *, clip, &bmain->movieclip) {
build_movieclip(clip);
}
+
+ /* Collections. */
+ build_scene_layer_collections(scene);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 6d4597fed9d..da788297a2f 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -396,30 +396,52 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
OperationKey ob_ubereval_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_OBJECT_UBEREVAL);
/* parenting */
- if (ob->parent) {
+ if (ob->parent != NULL) {
/* parent relationship */
build_object_parent(ob);
/* local -> parent */
- add_relation(local_transform_key, parent_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObLocal -> ObParent]");
+ add_relation(local_transform_key,
+ parent_transform_key,
+ DEPSREL_TYPE_COMPONENT_ORDER,
+ "[ObLocal -> ObParent]");
}
/* object constraints */
- if (ob->constraints.first) {
- OperationKey constraint_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_CONSTRAINTS);
+ if (ob->constraints.first != NULL) {
+ OperationKey constraint_key(&ob->id,
+ DEPSNODE_TYPE_TRANSFORM,
+ DEG_OPCODE_TRANSFORM_CONSTRAINTS);
/* constraint relations */
// TODO: provide base op
// XXX: this is broken
- build_constraints(scene, &ob->id, DEPSNODE_TYPE_TRANSFORM, "", &ob->constraints, NULL);
+ build_constraints(scene,
+ &ob->id,
+ DEPSNODE_TYPE_TRANSFORM,
+ "",
+ &ob->constraints,
+ NULL);
/* operation order */
- add_relation(base_op_key, constraint_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObBase-> Constraint Stack]");
- add_relation(constraint_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "[ObConstraints -> Done]");
+ add_relation(base_op_key,
+ constraint_key,
+ DEPSREL_TYPE_COMPONENT_ORDER,
+ "[ObBase-> Constraint Stack]");
+ add_relation(constraint_key,
+ final_transform_key,
+ DEPSREL_TYPE_COMPONENT_ORDER,
+ "[ObConstraints -> Done]");
// XXX
- add_relation(constraint_key, ob_ubereval_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
- add_relation(ob_ubereval_key, final_transform_key, DEPSREL_TYPE_COMPONENT_ORDER, "Temp Ubereval");
+ add_relation(constraint_key,
+ ob_ubereval_key,
+ DEPSREL_TYPE_COMPONENT_ORDER,
+ "Temp Ubereval");
+ add_relation(ob_ubereval_key,
+ final_transform_key,
+ DEPSREL_TYPE_COMPONENT_ORDER,
+ "Temp Ubereval");
}
else {
/* NOTE: Keep an eye here, we skip some relations here to "streamline"
@@ -448,7 +470,10 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
// XXX: This should be hooked up by the build_animdata code
if (needs_animdata_node(&ob->id)) {
ComponentKey adt_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
- add_relation(adt_key, local_transform_key, DEPSREL_TYPE_OPERATION, "Object Animation");
+ add_relation(adt_key,
+ local_transform_key,
+ DEPSREL_TYPE_OPERATION,
+ "Object Animation");
}
@@ -494,25 +519,48 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o
if (key != NULL) {
ComponentKey geometry_key((ID *)ob->data, DEPSNODE_TYPE_GEOMETRY);
ComponentKey key_key(&key->id, DEPSNODE_TYPE_GEOMETRY);
- add_relation(key_key, geometry_key, DEPSREL_TYPE_GEOMETRY_EVAL, "Shapekeys");
+ add_relation(key_key,
+ geometry_key,
+ DEPSREL_TYPE_GEOMETRY_EVAL,
+ "Shapekeys");
}
}
- /* particle systems */
- if (ob->particlesystem.first) {
+ /* Particle systems. */
+ if (ob->particlesystem.first != NULL) {
build_particles(scene, ob);
}
- /* grease pencil */
- if (ob->gpd) {
+ /* Grease pencil. */
+ if (ob->gpd != NULL) {
build_gpencil(ob->gpd);
}
+
+ /* Object that this is a proxy for. */
+ if (ob->proxy != NULL) {
+ ob->proxy->proxy_from = ob;
+ build_object(bmain, scene, ob->proxy);
+ /* TODO(sergey): This is an inverted relation, matches old depsgraph
+ * behavior and need to be investigated if it still need to be inverted.
+ */
+ ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
+ ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
+ add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
+ }
+
+ /* Object dupligroup. */
+ if (ob->dup_group != NULL) {
+ build_group(bmain, scene, ob, ob->dup_group);
+ }
}
void DepsgraphRelationBuilder::build_object_parent(Object *ob)
{
- /* XXX: for now, need to use the component key (not just direct to the parent op), or else the matrix doesn't get reset */
- // XXX: @sergey - it would be good if we got that backwards flushing working when tagging for updates
+ /* XXX: for now, need to use the component key (not just direct to the parent op),
+ * or else the matrix doesn't get reset/
+ */
+ // XXX: @sergey - it would be good if we got that backwards flushing working
+ // when tagging for updates.
//OperationKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_PARENT);
ComponentKey ob_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
@@ -1312,6 +1360,25 @@ void DepsgraphRelationBuilder::build_particles(Scene *scene, Object *ob)
// TODO...
}
+void DepsgraphRelationBuilder::build_cloth(Scene * /*scene*/,
+ Object *object,
+ ModifierData *md)
+{
+ OperationKey cache_key(&object->id,
+ DEPSNODE_TYPE_CACHE,
+ DEG_OPCODE_PLACEHOLDER,
+ "Cloth Modifier");
+ /* Cache component affects on modifier. */
+ OperationKey modifier_key(&object->id,
+ DEPSNODE_TYPE_GEOMETRY,
+ DEG_OPCODE_GEOMETRY_MODIFIER,
+ md->name);
+ add_relation(cache_key,
+ modifier_key,
+ DEPSREL_TYPE_TIME,
+ "Cloth Cache -> Cloth");
+}
+
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
{
@@ -1413,6 +1480,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
}
}
+ if (md->type == eModifierType_Cloth) {
+ build_cloth(scene, ob, md);
+ }
+
prev_mod_key = mod_key;
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 2e6fa7b5801..557f2dd36b8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -54,10 +54,12 @@ struct ID;
struct FCurve;
struct Group;
struct Key;
+struct LayerCollection;
struct Main;
struct Mask;
struct Material;
struct MTex;
+struct ModifierData;
struct MovieClip;
struct bNodeTree;
struct Object;
@@ -205,6 +207,7 @@ struct DepsgraphRelationBuilder
void build_world(World *world);
void build_rigidbody(Scene *scene);
void build_particles(Scene *scene, Object *ob);
+ void build_cloth(Scene *scene, Object *object, ModifierData *md);
void build_ik_pose(Object *ob,
bPoseChannel *pchan,
bConstraint *con,
@@ -232,6 +235,20 @@ struct DepsgraphRelationBuilder
void add_collision_relations(const OperationKey &key, Scene *scene, Object *ob, Group *group, int layer, bool dupli, const char *name);
void add_forcefield_relations(const OperationKey &key, Scene *scene, Object *ob, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name);
+ struct LayerCollectionState {
+ int index;
+ OperationKey init_key;
+ OperationKey done_key;
+ OperationKey prev_key;
+ };
+ void build_layer_collection(Scene *scene,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state);
+ void build_layer_collections(Scene *scene,
+ ListBase *layer_collections,
+ LayerCollectionState *state);
+ void build_scene_layer_collections(Scene *scene);
+
template <typename KeyType>
OperationDepsNode *find_operation_node(const KeyType &key);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer.cc
new file mode 100644
index 00000000000..46bef7a0131
--- /dev/null
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer.cc
@@ -0,0 +1,134 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Joshua Leung
+ * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+ * \ingroup depsgraph
+ *
+ * Methods for constructing depsgraph
+ */
+
+#include "intern/builder/deg_builder_relations.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <cstring> /* required for STREQ later on. */
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_blenlib.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+} /* extern "C" */
+
+#include "intern/builder/deg_builder.h"
+#include "intern/builder/deg_builder_pchanmap.h"
+
+#include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_operation.h"
+
+#include "intern/depsgraph_intern.h"
+#include "intern/depsgraph_types.h"
+
+#include "util/deg_util_foreach.h"
+
+namespace DEG {
+
+void DepsgraphRelationBuilder::build_layer_collection(Scene *scene,
+ LayerCollection *layer_collection,
+ LayerCollectionState *state)
+{
+ OperationKey layer_key(&scene->id,
+ DEPSNODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_SCENE_LAYER_EVAL,
+ layer_collection->scene_collection->name,
+ state->index);
+ add_relation(state->prev_key,
+ layer_key,
+ DEPSREL_TYPE_OPERATION,
+ "Layer collection order");
+
+ ++state->index;
+ state->prev_key = layer_key;
+
+ /* Recurs into nested layer collections. */
+ build_layer_collections(scene,
+ &layer_collection->layer_collections,
+ state);
+}
+
+void DepsgraphRelationBuilder::build_layer_collections(Scene *scene,
+ ListBase *layer_collections,
+ LayerCollectionState *state)
+{
+ LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
+ /* Recurs into the layer. */
+ build_layer_collection(scene, layer_collection, state);
+ }
+}
+
+void DepsgraphRelationBuilder::build_scene_layer_collections(Scene *scene)
+{
+ LayerCollectionState state;
+ state.index = 0;
+ LINKLIST_FOREACH (SceneLayer *, scene_layer, &scene->render_layers) {
+ OperationKey init_key(&scene->id,
+ DEPSNODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_SCENE_LAYER_INIT,
+ scene_layer->name);
+ OperationKey done_key(&scene->id,
+ DEPSNODE_TYPE_LAYER_COLLECTIONS,
+ DEG_OPCODE_SCENE_LAYER_DONE,
+ scene_layer->name);
+
+ state.init_key = init_key;
+ state.done_key = done_key;
+ state.prev_key = init_key;
+
+ build_layer_collections(scene,
+ &scene_layer->layer_collections,
+ &state);
+
+
+ add_relation(state.prev_key,
+ done_key,
+ DEPSREL_TYPE_OPERATION,
+ "Layer collection order");
+ }
+}
+
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
index 2f49d5b1645..3a007c4153a 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_scene.cc
@@ -75,28 +75,9 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
}
/* scene objects */
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
- /* object itself */
build_object(bmain, scene, ob);
-
- /* object that this is a proxy for */
- if (ob->proxy) {
- ob->proxy->proxy_from = ob;
- build_object(bmain, scene, ob->proxy);
- /* TODO(sergey): This is an inverted relation, matches old depsgraph
- * behavior and need to be investigated if it still need to be inverted.
- */
- ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
- ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
- add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
- }
-
- /* Object dupligroup. */
- if (ob->dup_group) {
- build_group(bmain, scene, ob, ob->dup_group);
- }
}
FOREACH_SCENE_OBJECT_END
@@ -135,6 +116,9 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
build_movieclip(clip);
}
+ /* Collections. */
+ build_scene_layer_collections(scene);
+
for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
it_op != m_graph->operations.end();
++it_op)
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
index 0d56ce71c7d..d49d5e1b000 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_graphviz.cc
@@ -83,15 +83,16 @@ static const int deg_debug_node_type_color_map[][2] = {
{DEPSNODE_TYPE_SUBGRAPH, 3},
/* Outer Types */
- {DEPSNODE_TYPE_PARAMETERS, 4},
- {DEPSNODE_TYPE_PROXY, 5},
- {DEPSNODE_TYPE_ANIMATION, 6},
- {DEPSNODE_TYPE_TRANSFORM, 7},
- {DEPSNODE_TYPE_GEOMETRY, 8},
- {DEPSNODE_TYPE_SEQUENCER, 9},
- {DEPSNODE_TYPE_SHADING, 10},
- {DEPSNODE_TYPE_CACHE, 11},
- {-1, 0}
+ {DEPSNODE_TYPE_PARAMETERS, 4},
+ {DEPSNODE_TYPE_PROXY, 5},
+ {DEPSNODE_TYPE_ANIMATION, 6},
+ {DEPSNODE_TYPE_TRANSFORM, 7},
+ {DEPSNODE_TYPE_GEOMETRY, 8},
+ {DEPSNODE_TYPE_SEQUENCER, 9},
+ {DEPSNODE_TYPE_SHADING, 10},
+ {DEPSNODE_TYPE_CACHE, 11},
+ {DEPSNODE_TYPE_LAYER_COLLECTIONS, 12},
+ {-1, 0}
};
#endif
@@ -403,6 +404,7 @@ static void deg_debug_graphviz_node(const DebugContext &ctx,
case DEPSNODE_TYPE_BONE:
case DEPSNODE_TYPE_SHADING:
case DEPSNODE_TYPE_CACHE:
+ case DEPSNODE_TYPE_LAYER_COLLECTIONS:
case DEPSNODE_TYPE_EVAL_PARTICLES:
{
ComponentDepsNode *comp_node = (ComponentDepsNode *)node;
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index a9df68beb36..8e7f8e01a59 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -56,8 +56,8 @@ extern "C" {
#include "DEG_depsgraph.h"
} /* extern "C" */
+#include "intern/builder/deg_builder.h"
#include "intern/eval/deg_eval_flush.h"
-
#include "intern/nodes/deg_node.h"
#include "intern/nodes/deg_node_component.h"
#include "intern/nodes/deg_node_operation.h"
@@ -348,6 +348,27 @@ void DEG_graph_on_visible_update(Main *bmain, Scene *scene)
GHASH_FOREACH_END();
}
scene->lay_updated |= graph->layers;
+ /* Special trick to get local view to work. */
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ id_node->layers = 0;
+ }
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ id_node->layers |= base->lay;
+ }
+ DEG::deg_graph_build_flush_layers(graph);
+ LINKLIST_FOREACH (Base *, base, &scene->base) {
+ Object *object = base->object;
+ DEG::IDDepsNode *id_node = graph->find_id_node(&object->id);
+ GHASH_FOREACH_BEGIN(DEG::ComponentDepsNode *, comp, id_node->components)
+ {
+ id_node->layers |= comp->layers;
+ }
+ GHASH_FOREACH_END();
+ }
}
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
diff --git a/source/blender/depsgraph/intern/depsgraph_type_defines.cc b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
index 39c189629f2..6c3e3805169 100644
--- a/source/blender/depsgraph/intern/depsgraph_type_defines.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type_defines.cc
@@ -130,6 +130,10 @@ static const char *stringify_opcode(eDepsOperation_Code opcode)
STRINGIFY_OPCODE(BONE_DONE);
STRINGIFY_OPCODE(PSYS_EVAL);
+ STRINGIFY_OPCODE(SCENE_LAYER_INIT);
+ STRINGIFY_OPCODE(SCENE_LAYER_EVAL);
+ STRINGIFY_OPCODE(SCENE_LAYER_DONE);
+
case DEG_NUM_OPCODES: return "SpecialCase";
#undef STRINGIFY_OPCODE
}
diff --git a/source/blender/depsgraph/intern/depsgraph_types.h b/source/blender/depsgraph/intern/depsgraph_types.h
index effd34a0eb9..6b9a6e0191e 100644
--- a/source/blender/depsgraph/intern/depsgraph_types.h
+++ b/source/blender/depsgraph/intern/depsgraph_types.h
@@ -44,9 +44,6 @@
#include <string>
#include <vector>
-using std::string;
-using std::vector;
-
struct bAction;
struct ChannelDriver;
struct ModifierData;
@@ -56,6 +53,9 @@ struct FCurve;
namespace DEG {
+using std::string;
+using std::vector;
+
/* Evaluation Operation for atomic operation */
// XXX: move this to another header that can be exposed?
typedef function<void(struct EvaluationContext *)> DepsEvalOperationCb;
@@ -89,52 +89,54 @@ typedef enum eDepsNode_Type {
/* **** Generic Types **** */
/* "Current Scene" - basically whatever kicks off the evaluation process. */
- DEPSNODE_TYPE_ROOT = 1,
+ DEPSNODE_TYPE_ROOT,
/* Time-Source */
- DEPSNODE_TYPE_TIMESOURCE = 2,
+ DEPSNODE_TYPE_TIMESOURCE,
/* ID-Block reference - used as landmarks/collection point for components,
* but not usually part of main graph.
*/
- DEPSNODE_TYPE_ID_REF = 3,
+ DEPSNODE_TYPE_ID_REF,
/* Isolated sub-graph - used for keeping instanced data separate from
* instances using them.
*/
- DEPSNODE_TYPE_SUBGRAPH = 4,
+ DEPSNODE_TYPE_SUBGRAPH,
/* **** Outer Types **** */
/* Parameters Component - Default when nothing else fits
* (i.e. just SDNA property setting).
*/
- DEPSNODE_TYPE_PARAMETERS = 11,
+ DEPSNODE_TYPE_PARAMETERS,
/* Generic "Proxy-Inherit" Component
* XXX: Also for instancing of subgraphs?
*/
- DEPSNODE_TYPE_PROXY = 12,
+ DEPSNODE_TYPE_PROXY,
/* Animation Component
*
* XXX: merge in with parameters?
*/
- DEPSNODE_TYPE_ANIMATION = 13,
+ DEPSNODE_TYPE_ANIMATION,
/* Transform Component (Parenting/Constraints) */
- DEPSNODE_TYPE_TRANSFORM = 14,
+ DEPSNODE_TYPE_TRANSFORM,
/* Geometry Component (DerivedMesh/Displist) */
- DEPSNODE_TYPE_GEOMETRY = 15,
+ DEPSNODE_TYPE_GEOMETRY,
/* Sequencer Component (Scene Only) */
- DEPSNODE_TYPE_SEQUENCER = 16,
+ DEPSNODE_TYPE_SEQUENCER,
/* **** Evaluation-Related Outer Types (with Subdata) **** */
/* Pose Component - Owner/Container of Bones Eval */
- DEPSNODE_TYPE_EVAL_POSE = 21,
+ DEPSNODE_TYPE_EVAL_POSE,
/* Bone Component - Child/Subcomponent of Pose */
- DEPSNODE_TYPE_BONE = 22,
+ DEPSNODE_TYPE_BONE,
/* Particle Systems Component */
- DEPSNODE_TYPE_EVAL_PARTICLES = 23,
+ DEPSNODE_TYPE_EVAL_PARTICLES,
/* Material Shading Component */
- DEPSNODE_TYPE_SHADING = 24,
+ DEPSNODE_TYPE_SHADING,
/* Cache Component */
- DEPSNODE_TYPE_CACHE = 25,
+ DEPSNODE_TYPE_CACHE,
+ /* Component which contains all operations needed for layer collections evaluation. */
+ DEPSNODE_TYPE_LAYER_COLLECTIONS,
} eDepsNode_Type;
/* Identifiers for common operations (as an enum). */
@@ -243,6 +245,11 @@ typedef enum eDepsOperation_Code {
/* XXX: placeholder - Particle System eval */
DEG_OPCODE_PSYS_EVAL,
+ /* Collections ------------------------------------- */
+ DEG_OPCODE_SCENE_LAYER_INIT,
+ DEG_OPCODE_SCENE_LAYER_EVAL,
+ DEG_OPCODE_SCENE_LAYER_DONE,
+
DEG_NUM_OPCODES,
} eDepsOperation_Code;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index 3a042535d26..e739bc9dbb5 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -95,105 +95,38 @@ static void deg_task_run_func(TaskPool *pool,
/* Should only be the case for NOOPs, which never get to this point. */
BLI_assert(node->evaluate);
- while (true) {
- /* Get context. */
- /* TODO: Who initialises this? "Init" operations aren't able to
- * initialise it!!!
- */
- /* TODO(sergey): We don't use component contexts at this moment. */
- /* ComponentDepsNode *comp = node->owner; */
- BLI_assert(node->owner != NULL);
-
- /* Since we're not leaving the thread for until the graph branches it is
- * possible to have NO-OP on the way. for which evaluate() will be NULL.
- * but that's all fine, we'll just scheduler it's children.
- */
- if (node->evaluate) {
+ /* Get context. */
+ /* TODO: Who initialises this? "Init" operations aren't able to
+ * initialise it!!!
+ */
+ /* TODO(sergey): We don't use component contexts at this moment. */
+ /* ComponentDepsNode *comp = node->owner; */
+ BLI_assert(node->owner != NULL);
+
+ /* Since we're not leaving the thread for until the graph branches it is
+ * possible to have NO-OP on the way. for which evaluate() will be NULL.
+ * but that's all fine, we'll just scheduler it's children.
+ */
+ if (node->evaluate) {
/* Take note of current time. */
#ifdef USE_DEBUGGER
- double start_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_started(state->graph, node);
+ double start_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_started(state->graph, node);
#endif
- /* Perform operation. */
- node->evaluate(state->eval_ctx);
+ /* Perform operation. */
+ node->evaluate(state->eval_ctx);
/* Note how long this took. */
#ifdef USE_DEBUGGER
- double end_time = PIL_check_seconds_timer();
- DepsgraphDebug::task_completed(state->graph,
- node,
- end_time - start_time);
+ double end_time = PIL_check_seconds_timer();
+ DepsgraphDebug::task_completed(state->graph,
+ node,
+ end_time - start_time);
#endif
- }
-
- /* If there's only one outgoing link we try to immediately switch to
- * that node evaluation, without leaving the thread.
- *
- * It's only doable if the child don't have extra relations or all they
- * are satisfied.
- *
- * TODO(sergey): Checks here can be de-duplicated with the ones from
- * schedule_node(), however, how to do it nicely?
- */
- if (node->outlinks.size() == 1) {
- DepsRelation *rel = node->outlinks[0];
- OperationDepsNode *child = (OperationDepsNode *)rel->to;
- BLI_assert(child->type == DEPSNODE_TYPE_OPERATION);
- if (!child->scheduled) {
- unsigned int id_layers = child->owner->owner->layers;
- if (!((child->flag & DEPSOP_FLAG_NEEDS_UPDATE) != 0 &&
- (id_layers & state->layers) != 0))
- {
- /* Node does not need an update, so can;t continue with the
- * chain and need to switch to another one by leaving the
- * thread.
- */
- break;
- }
- if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
- BLI_assert(child->num_links_pending > 0);
- atomic_sub_and_fetch_uint32(&child->num_links_pending, 1);
- }
- if (child->num_links_pending == 0) {
- bool is_scheduled = atomic_fetch_and_or_uint8(
- (uint8_t *)&child->scheduled, (uint8_t)true);
- if (!is_scheduled) {
- /* Node was not scheduled, switch to it! */
- node = child;
- }
- else {
- /* Someone else scheduled the node, leaving us
- * unemployed in this thread, we're leaving.
- */
- break;
- }
- }
- else {
- /* There are other dependencies on the child, can't do
- * anything in the current thread.
- */
- break;
- }
- }
- else {
- /* Happens when having cyclic dependencies.
- *
- * Nothing to do here, single child was already scheduled, we
- * can leave the thread now.
- */
- break;
- }
- }
- else {
- /* TODO(sergey): It's possible to use one of the outgoing relations
- * as a chain which we'll try to keep alive, but it's a bit more
- * involved change.
- */
- schedule_children(pool, state->graph, node, state->layers, thread_id);
- break;
- }
}
+
+ schedule_children(pool, state->graph, node, state->layers, thread_id);
}
typedef struct CalculatePengindData {
@@ -378,12 +311,19 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
state.graph = graph;
state.layers = layers;
- TaskScheduler *task_scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &state);
+ TaskScheduler *task_scheduler;
+ bool need_free_scheduler;
if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- BLI_pool_set_num_threads(task_pool, 1);
+ task_scheduler = BLI_task_scheduler_create(1);
+ need_free_scheduler = true;
}
+ else {
+ task_scheduler = BLI_task_scheduler_get();
+ need_free_scheduler = false;
+ }
+
+ TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
calculate_pending_parents(graph, layers);
@@ -410,6 +350,10 @@ void deg_evaluate_on_refresh(EvaluationContext *eval_ctx,
/* Clear any uncleared tags - just in case. */
deg_graph_clear_tags(graph);
+
+ if (need_free_scheduler) {
+ BLI_task_scheduler_free(task_scheduler);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 7c6c25bef0d..e10f86f6e95 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -180,6 +180,11 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
comp_node->done = 1;
/* Flush to nodes along links... */
+ /* TODO(sergey): This is mainly giving speedup due ot less queue pushes, which
+ * reduces number of memory allocations.
+ *
+ * We should try solve the allocation issue instead of doing crazy things here.
+ */
if (node->outlinks.size() == 1) {
OperationDepsNode *to_node = (OperationDepsNode *)node->outlinks[0]->to;
if (to_node->scheduled == false) {
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.cc b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
index 06f91ac7fdc..9549cbcfeef 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.cc
@@ -406,6 +406,11 @@ static DepsNodeFactoryImpl<ShadingComponentDepsNode> DNTI_SHADING;
DEG_DEPSNODE_DEFINE(CacheComponentDepsNode, DEPSNODE_TYPE_CACHE, "Cache Component");
static DepsNodeFactoryImpl<CacheComponentDepsNode> DNTI_CACHE;
+/* Layer COllections Defines ============================ */
+
+DEG_DEPSNODE_DEFINE(LayerCollectionsDepsNode, DEPSNODE_TYPE_LAYER_COLLECTIONS, "Layer Collections Component");
+static DepsNodeFactoryImpl<LayerCollectionsDepsNode> DNTI_LAYER_COLLECTIONS;
+
/* Node Types Register =================================== */
@@ -425,6 +430,8 @@ void deg_register_component_depsnodes()
deg_register_node_typeinfo(&DNTI_SHADING);
deg_register_node_typeinfo(&DNTI_CACHE);
+
+ deg_register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/nodes/deg_node_component.h b/source/blender/depsgraph/intern/nodes/deg_node_component.h
index 969771a29c9..bb94401562d 100644
--- a/source/blender/depsgraph/intern/nodes/deg_node_component.h
+++ b/source/blender/depsgraph/intern/nodes/deg_node_component.h
@@ -201,6 +201,10 @@ struct CacheComponentDepsNode : public ComponentDepsNode {
DEG_DEPSNODE_DECLARE;
};
+struct LayerCollectionsDepsNode : public ComponentDepsNode {
+ DEG_DEPSNODE_DECLARE;
+};
+
void deg_register_component_depsnodes();
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index d5b54e8a746..e921a65bfe8 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -27,7 +27,10 @@ set(INC
.
intern
engines/clay
+ engines/eevee
+ modes
+ ../blenfont
../blenkernel
../blenlib
../blentranslation
@@ -40,6 +43,7 @@ set(INC
../editors/space_view3d
../render/extern/include
../render/intern/include
+ ../windowmanager
../../../intern/glew-mx
../../../intern/guardedalloc
@@ -51,14 +55,39 @@ set(INC_SYS
set(SRC
intern/draw_manager.c
- intern/draw_mode_pass.c
+ intern/draw_common.c
intern/draw_cache.c
+ intern/draw_view.c
+ intern/draw_armature.c
+
engines/clay/clay.c
+ engines/clay/clay.h
+
+ engines/eevee/eevee.c
+ engines/eevee/eevee_lights.c
+ engines/eevee/eevee.h
+ engines/eevee/eevee_private.h
+
+ modes/object_mode.c
+ modes/edit_armature_mode.c
+ modes/edit_curve_mode.c
+ modes/edit_lattice_mode.c
+ modes/edit_mesh_mode.c
+ modes/edit_metaball_mode.c
+ modes/edit_surface_mode.c
+ modes/edit_text_mode.c
+ modes/paint_texture_mode.c
+ modes/paint_vertex_mode.c
+ modes/paint_weight_mode.c
+ modes/particle_mode.c
+ modes/pose_mode.c
+ modes/sculpt_mode.c
intern/DRW_render.h
- intern/draw_mode_pass.h
+ intern/draw_common.h
intern/draw_cache.h
- engines/clay/clay.h
+ intern/draw_view.h
+ modes/draw_mode_engines.h
./DRW_engine.h
)
@@ -72,6 +101,32 @@ data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/tonemap_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
+
+data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_geom_tri.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_geom_edge.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_loosevert_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_facedot_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_facedot_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_mix_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_facefill_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_overlay_facefill_frag.glsl SRC)
+data_to_c_simple(modes/shaders/edit_normals_vert.glsl SRC)
+data_to_c_simple(modes/shaders/edit_normals_geom.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_resolve_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_expand_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_outline_detect_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_grid_frag.glsl SRC)
+data_to_c_simple(modes/shaders/object_grid_vert.glsl SRC)
+
list(APPEND INC
)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 4f86e3fcd91..87cfa8e8e3b 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -26,20 +26,40 @@
#ifndef __DRW_ENGINE_H__
#define __DRW_ENGINE_H__
-//#define WITH_VIEWPORT_CACHE_TEST
-
+struct CollectionEngineSettings;
struct DRWPass;
struct Material;
struct Scene;
+struct DrawEngineType;
+struct IDProperty;
+struct bContext;
+struct Object;
+
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+ struct GPUFrameBuffer *default_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+} DefaultTextureList;
-void DRW_engines_init(void);
+void DRW_engines_register(void);
void DRW_engines_free(void);
+void DRW_engine_register(struct DrawEngineType *draw_engine_type);
+
+void DRW_draw_view(const struct bContext *C);
+
+void DRW_object_engine_data_free(struct Object *ob);
+
/* This is here because GPUViewport needs it */
void DRW_pass_free(struct DRWPass *pass);
-/* Settings */
-void *DRW_material_settings_get(struct Material *ma, const char *engine_name);
-void *DRW_render_settings_get(struct Scene *scene, const char *engine_name);
+/* Mode engines initialization */
+void OBJECT_collection_settings_create(struct IDProperty *properties);
+void EDIT_MESH_collection_settings_create(struct IDProperty *properties);
+void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties);
-#endif /* __DRW_ENGINE_H__ */ \ No newline at end of file
+#endif /* __DRW_ENGINE_H__ */
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c
index 0572f4a0dc9..23cfe82276f 100644
--- a/source/blender/draw/engines/clay/clay.c
+++ b/source/blender/draw/engines/clay/clay.c
@@ -22,6 +22,7 @@
#include "DRW_render.h"
#include "BKE_icons.h"
+#include "BKE_idprop.h"
#include "BKE_main.h"
#include "BLI_dynstr.h"
@@ -42,9 +43,8 @@
extern char datatoc_clay_frag_glsl[];
extern char datatoc_clay_vert_glsl[];
extern char datatoc_ssao_alchemy_glsl[];
-extern char datatoc_ssao_groundtruth_glsl[];
-/* Storage */
+/* *********** LISTS *********** */
/* UBOs data needs to be 16 byte aligned (size of vec4) */
/* Reminder : float, int, bool are 4 bytes */
@@ -64,24 +64,6 @@ typedef struct CLAY_UBO_Storage {
CLAY_UBO_Material materials[MAX_CLAY_MAT];
} CLAY_UBO_Storage;
-static struct CLAY_data {
- /* Depth Pre Pass */
- struct GPUShader *depth_sh;
- /* Shading Pass */
- struct GPUShader *clay_sh;
-
- /* Matcap textures */
- struct GPUTexture *matcap_array;
- float matcap_colors[24][3];
-
- /* Ssao */
- float winmat[4][4];
- float viewvecs[3][4];
- float ssao_params[4];
- struct GPUTexture *jitter_tx;
- struct GPUTexture *sampling_tx;
-} data = {NULL};
-
/* GPUViewport.storage
* Is freed everytime the viewport engine changes */
typedef struct CLAY_Storage {
@@ -91,52 +73,78 @@ typedef struct CLAY_Storage {
DRWShadingGroup *shgrps[MAX_CLAY_MAT];
} CLAY_Storage;
-/* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
-static int ubo_mat_idxs[MAX_CLAY_MAT] = {0};
-
/* keep it under MAX_STORAGE */
typedef struct CLAY_StorageList {
struct CLAY_Storage *storage;
struct GPUUniformBuffer *mat_ubo;
+ struct g_data *g_data;
} CLAY_StorageList;
/* keep it under MAX_BUFFERS */
-typedef struct CLAY_FramebufferList{
+typedef struct CLAY_FramebufferList {
/* default */
struct GPUFrameBuffer *default_fb;
/* engine specific */
- struct GPUFrameBuffer *downsample_depth;
+ struct GPUFrameBuffer *dupli_depth;
} CLAY_FramebufferList;
/* keep it under MAX_TEXTURES */
-typedef struct CLAY_TextureList{
+typedef struct CLAY_TextureList {
/* default */
struct GPUTexture *color;
struct GPUTexture *depth;
/* engine specific */
- struct GPUTexture *depth_low;
+ struct GPUTexture *depth_dup;
} CLAY_TextureList;
-/* for clarity follow the same layout as CLAY_TextureList */
-enum {
- SCENE_COLOR,
- SCENE_DEPTH,
- SCENE_DEPTH_LOW,
-};
-
/* keep it under MAX_PASSES */
-typedef struct CLAY_PassList{
- /* default */
- struct DRWPass *non_meshes_pass;
- struct DRWPass *ob_center_pass;
- /* engine specific */
+typedef struct CLAY_PassList {
struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
struct DRWPass *clay_pass;
- struct DRWPass *wire_overlay_pass;
- struct DRWPass *wire_outline_pass;
+ struct g_data *g_data;
} CLAY_PassList;
-//#define GTAO
+typedef struct CLAY_Data {
+ void *engine_type;
+ CLAY_FramebufferList *fbl;
+ CLAY_TextureList *txl;
+ CLAY_PassList *psl;
+ CLAY_StorageList *stl;
+} CLAY_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Depth Pre Pass */
+ struct GPUShader *depth_sh;
+ /* Shading Pass */
+ struct GPUShader *clay_sh;
+
+ /* Matcap textures */
+ struct GPUTexture *matcap_array;
+ float matcap_colors[24][3];
+
+ /* Ssao */
+ float winmat[4][4];
+ float viewvecs[3][4];
+ float ssao_params[4];
+ int cached_sample_num;
+ struct GPUTexture *jitter_tx;
+ struct GPUTexture *sampling_tx;
+
+ /* Just a serie of int from 0 to MAX_CLAY_MAT-1 */
+ int ubo_mat_idxs[MAX_CLAY_MAT];
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ DRWShadingGroup *depth_shgrp;
+ DRWShadingGroup *depth_shgrp_select;
+ DRWShadingGroup *depth_shgrp_active;
+ DRWShadingGroup *depth_shgrp_cull;
+ DRWShadingGroup *depth_shgrp_cull_select;
+ DRWShadingGroup *depth_shgrp_cull_active;
+} g_data; /* Transient data */
/* Functions */
@@ -151,15 +159,15 @@ static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
/* Find overall color */
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
- data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
- data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
- data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
+ e_data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
+ e_data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
+ e_data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
}
}
- data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
- data.matcap_colors[layer][1] /= 16.0f * 2.0f;
- data.matcap_colors[layer][2] /= 16.0f * 2.0f;
+ e_data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
+ e_data.matcap_colors[layer][1] /= 16.0f * 2.0f;
+ e_data.matcap_colors[layer][2] /= 16.0f * 2.0f;
}
static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
@@ -237,56 +245,22 @@ static struct GPUTexture *create_jitter_texture(void)
/* TODO replace by something more evenly distributed like blue noise */
for (i = 0; i < 64 * 64; i++) {
-#ifdef GTAO
- jitter[i][0] = BLI_frand();
- jitter[i][1] = BLI_frand();
-#else
jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
normalize_v2(jitter[i]);
-#endif
}
return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
}
-static void clay_material_settings_init(MaterialEngineSettingsClay *ma)
-{
- ma->matcap_icon = ICON_MATCAP_01;
- ma->matcap_rot = 0.0f;
- ma->matcap_hue = 0.5f;
- ma->matcap_sat = 0.5f;
- ma->matcap_val = 0.5f;
- ma->ssao_distance = 0.2;
- ma->ssao_attenuation = 1.0f;
- ma->ssao_factor_cavity = 1.0f;
- ma->ssao_factor_edge = 1.0f;
-}
-
-RenderEngineSettings *CLAY_render_settings_create(void)
+static void CLAY_engine_init(void *vedata)
{
- RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay");
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
+ CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
+ CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
- clay_material_settings_init((MaterialEngineSettingsClay *)settings);
-
- settings->ssao_samples = 32;
-
- return (RenderEngineSettings *)settings;
-}
-
-MaterialEngineSettings *CLAY_material_settings_create(void)
-{
- MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay");
-
- clay_material_settings_init(settings);
-
- return (MaterialEngineSettings *)settings;
-}
-
-static void CLAY_engine_init(CLAY_StorageList *stl)
-{
/* Create Texture Array */
- if (!data.matcap_array) {
+ if (!e_data.matcap_array) {
PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
/* TODO only load used matcaps */
@@ -315,27 +289,22 @@ static void CLAY_engine_init(CLAY_StorageList *stl)
prv[22] = UI_icon_to_preview(ICON_MATCAP_23);
prv[23] = UI_icon_to_preview(ICON_MATCAP_24);
- data.matcap_array = load_matcaps(prv, 24);
+ e_data.matcap_array = load_matcaps(prv, 24);
}
/* AO Jitter */
- if (!data.jitter_tx) {
- data.jitter_tx = create_jitter_texture();
+ if (!e_data.jitter_tx) {
+ e_data.jitter_tx = create_jitter_texture();
}
- /* AO Samples */
- /* TODO use hammersley sequence */
- if (!data.sampling_tx) {
- data.sampling_tx = create_spiral_sample_texture(500);
- }
/* Depth prepass */
- if (!data.depth_sh) {
- data.depth_sh = DRW_shader_create_3D_depth_only();
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
}
/* Shading pass */
- if (!data.clay_sh) {
+ if (!e_data.clay_sh) {
DynStr *ds = BLI_dynstr_new();
const char *max_mat =
"#define MAX_MATERIAL 512\n"
@@ -345,15 +314,11 @@ static void CLAY_engine_init(CLAY_StorageList *stl)
char *matcap_with_ao;
BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
-#ifdef GTAO
- BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl);
-#else
BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
-#endif
matcap_with_ao = BLI_dynstr_get_cstring(ds);
- data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
+ e_data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
BLI_dynstr_free(ds);
MEM_freeN(matcap_with_ao);
@@ -367,86 +332,103 @@ static void CLAY_engine_init(CLAY_StorageList *stl)
stl->mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
}
- if (ubo_mat_idxs[1] == 0) {
+ if (e_data.ubo_mat_idxs[1] == 0) {
/* Just int to have pointers to them */
for (int i = 0; i < MAX_CLAY_MAT; ++i) {
- ubo_mat_idxs[i] = i;
+ e_data.ubo_mat_idxs[i] = i;
}
}
-}
-static void CLAY_ssao_setup(void)
-{
- float invproj[4][4];
- float dfdyfacs[2];
- bool is_persp = DRW_viewport_is_persp_get();
- /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
- float viewvecs[3][4] = {
- {-1.0f, -1.0f, -1.0f, 1.0f},
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f}
- };
- int i;
- float *size = DRW_viewport_size_get();
- RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
-
- DRW_get_dfdy_factors(dfdyfacs);
-
- data.ssao_params[0] = settings->ssao_samples;
- data.ssao_params[1] = size[0] / 64.0;
- data.ssao_params[2] = size[1] / 64.0;
- data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
-
- /* invert the view matrix */
- DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN);
- invert_m4_m4(invproj, data.winmat);
-
- /* convert the view vectors to view space */
- for (i = 0; i < 3; i++) {
- mul_m4_v4(invproj, viewvecs[i]);
- /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
- if (is_persp)
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
- viewvecs[i][3] = 1.0;
-
- copy_v4_v4(data.viewvecs[i], viewvecs[i]);
+ {
+ float *viewport_size = DRW_viewport_size_get();
+ DRWFboTexture tex = {&txl->depth_dup, DRW_BUF_DEPTH_24};
+ DRW_framebuffer_init(&fbl->dupli_depth,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
}
- /* we need to store the differences */
- data.viewvecs[1][0] -= data.viewvecs[0][0];
- data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1];
+ /* SSAO setup */
+ {
+ int ssao_samples = 32; /* XXX get from render settings */
+ float invproj[4][4];
+ float dfdyfacs[2];
+ bool is_persp = DRW_viewport_is_persp_get();
+ /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+ float viewvecs[3][4] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+ int i;
+ float *size = DRW_viewport_size_get();
+
+ DRW_get_dfdy_factors(dfdyfacs);
+
+ e_data.ssao_params[0] = ssao_samples;
+ e_data.ssao_params[1] = size[0] / 64.0;
+ e_data.ssao_params[2] = size[1] / 64.0;
+ e_data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+
+ /* invert the view matrix */
+ DRW_viewport_matrix_get(e_data.winmat, DRW_MAT_WIN);
+ invert_m4_m4(invproj, e_data.winmat);
+
+ /* convert the view vectors to view space */
+ for (i = 0; i < 3; i++) {
+ mul_m4_v4(invproj, viewvecs[i]);
+ /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ if (is_persp)
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+ viewvecs[i][3] = 1.0;
+
+ copy_v4_v4(e_data.viewvecs[i], viewvecs[i]);
+ }
+
+ /* we need to store the differences */
+ e_data.viewvecs[1][0] -= e_data.viewvecs[0][0];
+ e_data.viewvecs[1][1] = e_data.viewvecs[2][1] - e_data.viewvecs[0][1];
+
+ /* calculate a depth offset as well */
+ if (!is_persp) {
+ float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ mul_m4_v4(invproj, vec_far);
+ mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+ e_data.viewvecs[1][2] = vec_far[2] - e_data.viewvecs[0][2];
+ }
- /* calculate a depth offset as well */
- if (!is_persp) {
- float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
- mul_m4_v4(invproj, vec_far);
- mul_v3_fl(vec_far, 1.0f / vec_far[3]);
- data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2];
+ /* AO Samples Tex */
+ if (e_data.sampling_tx && (e_data.cached_sample_num != ssao_samples)) {
+ DRW_texture_free(e_data.sampling_tx);
+ e_data.sampling_tx = NULL;
+ }
+
+ if (!e_data.sampling_tx) {
+ e_data.sampling_tx = create_spiral_sample_texture(ssao_samples);
+ e_data.cached_sample_num = ssao_samples;
+ }
}
}
-static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *material_id)
+static DRWShadingGroup *CLAY_shgroup_create(CLAY_Data *vedata, DRWPass *pass, int *material_id)
{
+ CLAY_TextureList *txl = ((CLAY_Data *)vedata)->txl;
const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3;
- //CLAY_UBO_Material *mat = &data.mat_storage.materials[0];
- DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass);
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.clay_sh, pass);
DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
- DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc);
- DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc);
- DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat);
- DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3);
- DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1);
- DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24);
+ DRW_shgroup_uniform_buffer(grp, "depthtex", &txl->depth_dup, depthloc);
+ DRW_shgroup_uniform_texture(grp, "matcaps", e_data.matcap_array, matcaploc);
+ DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)e_data.winmat);
+ DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)e_data.viewvecs, 3);
+ DRW_shgroup_uniform_vec4(grp, "ssao_params", e_data.ssao_params, 1);
+ DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)e_data.matcap_colors, 24);
DRW_shgroup_uniform_int(grp, "mat_id", material_id, 1);
-#ifndef GTAO
- DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc);
- DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc);
-#endif
+ DRW_shgroup_uniform_texture(grp, "ssao_jitter", e_data.jitter_tx, jitterloc);
+ DRW_shgroup_uniform_texture(grp, "ssao_samples", e_data.sampling_tx, sampleloc);
return grp;
}
@@ -457,8 +439,7 @@ static int search_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matc
{
/* For now just use a linear search and test all parameters */
/* TODO make a hash table */
- for (int i = 0; i < storage->ubo_current_id; ++i)
- {
+ for (int i = 0; i < storage->ubo_current_id; ++i) {
CLAY_UBO_Material *ubo = &storage->mat_storage.materials[i];
if ((ubo->matcap_rot[0] == cosf(matcap_rot * 3.14159f * 2.0f)) &&
@@ -492,7 +473,8 @@ static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap
ubo->matcap_hsv[1] = matcap_sat * 2.0f;
ubo->matcap_hsv[2] = matcap_val * 2.0f;
- ubo->ssao_params_var[0] = ssao_distance;
+ /* small optimisation : make samples not spread if we don't need ssao */
+ ubo->ssao_params_var[0] = (ssao_factor_cavity + ssao_factor_edge > 0.0f) ? ssao_distance : 0.0f;
ubo->ssao_params_var[1] = ssao_factor_cavity;
ubo->ssao_params_var[2] = ssao_factor_edge;
ubo->ssao_params_var[3] = ssao_attenuation;
@@ -504,269 +486,187 @@ static int push_mat_to_ubo(CLAY_Storage *storage, float matcap_rot, float matcap
return id;
}
-static int mat_in_ubo(CLAY_Storage *storage, struct GPUUniformBuffer *ubo, DRWPass *pass,
- float matcap_rot, float matcap_hue, float matcap_sat,
+static int mat_in_ubo(CLAY_Storage *storage, float matcap_rot, float matcap_hue, float matcap_sat,
float matcap_val, float ssao_distance, float ssao_factor_cavity,
float ssao_factor_edge, float ssao_attenuation, int matcap_icon)
{
- int id;
-
/* Search material in UBO */
- id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
- ssao_distance, ssao_factor_cavity, ssao_factor_edge,
- ssao_attenuation, matcap_icon);
+ int id = search_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
+ ssao_distance, ssao_factor_cavity, ssao_factor_edge,
+ ssao_attenuation, matcap_icon);
/* if not found create it */
if (id == -1) {
id = push_mat_to_ubo(storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
ssao_distance, ssao_factor_cavity, ssao_factor_edge,
ssao_attenuation, matcap_icon);
-
- storage->shgrps[id] = CLAY_shgroup_create(pass, &ubo_mat_idxs[id]);
-
- /* if it's the first shgrp, pass bind the material UBO */
- if (storage->ubo_current_id == 1) {
- DRW_shgroup_uniform_block(storage->shgrps[0], "material_block", ubo, 0);
- }
}
return id;
}
-/* Safe way to get override values */
-static void override_setting(CollectionEngineSettings *ces, const char *name, void *ret)
+static DRWShadingGroup *CLAY_object_shgrp_get(CLAY_Data *vedata, Object *ob, CLAY_StorageList *stl, CLAY_PassList *psl)
{
- CollectionEngineProperty *cep = BKE_collection_engine_property_get(ces, name);
-
- if (cep == NULL) {
- return;
- }
+ DRWShadingGroup **shgrps = stl->storage->shgrps;
+ IDProperty *props = BKE_object_collection_engine_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY);
- if ((cep->flag & COLLECTION_PROP_USE) == 0) {
- return;
+ /* Default Settings */
+ float matcap_rot = BKE_collection_engine_property_value_get_float(props, "matcap_rotation");
+ float matcap_hue = BKE_collection_engine_property_value_get_float(props, "matcap_hue");
+ float matcap_sat = BKE_collection_engine_property_value_get_float(props, "matcap_saturation");
+ float matcap_val = BKE_collection_engine_property_value_get_float(props, "matcap_value");
+ float ssao_distance = BKE_collection_engine_property_value_get_float(props, "ssao_distance");
+ float ssao_factor_cavity = BKE_collection_engine_property_value_get_float(props, "ssao_factor_cavity");
+ float ssao_factor_edge = BKE_collection_engine_property_value_get_float(props, "ssao_factor_edge");
+ float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation");
+ int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon");
+
+ int id = mat_in_ubo(stl->storage, matcap_rot, matcap_hue, matcap_sat, matcap_val,
+ ssao_distance, ssao_factor_cavity, ssao_factor_edge,
+ ssao_attenuation, matcap_icon);
+
+ if (shgrps[id] == NULL) {
+ shgrps[id] = CLAY_shgroup_create(vedata, psl->clay_pass, &e_data.ubo_mat_idxs[id]);
+ /* if it's the first shgrp, pass bind the material UBO */
+ if (stl->storage->ubo_current_id == 1) {
+ DRW_shgroup_uniform_block(shgrps[0], "material_block", stl->mat_ubo, 0);
+ }
}
- if (cep->type == COLLECTION_PROP_TYPE_INT) {
- CollectionEnginePropertyInt *prop = (CollectionEnginePropertyInt *)cep;
- *((int *)ret) = prop->value;
- }
- else {
- CollectionEnginePropertyFloat *prop = (CollectionEnginePropertyFloat *)cep;
- *((float *)ret) = prop->value;
- }
+ return shgrps[id];
}
-static DRWShadingGroup *CLAY_object_shgrp_get(Object *ob, CLAY_StorageList *stl, DRWPass *pass)
+static void CLAY_cache_init(void *vedata)
{
- MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
- CollectionEngineSettings *ces = ob->collection_settings;
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- /* Default Settings */
- float matcap_rot = settings->matcap_rot;
- float matcap_hue = settings->matcap_hue;
- float matcap_sat = settings->matcap_sat;
- float matcap_val = settings->matcap_val;
- float ssao_distance = settings->ssao_distance;
- float ssao_factor_cavity = settings->ssao_factor_cavity;
- float ssao_factor_edge = settings->ssao_factor_edge;
- float ssao_attenuation = settings->ssao_attenuation;
- int matcap_icon = settings->matcap_icon;
-
- /* Override settings */
- if (ces) {
- override_setting(ces, "matcap_rotation", &matcap_rot);
- override_setting(ces, "matcap_hue", &matcap_hue);
- override_setting(ces, "matcap_saturation", &matcap_sat);
- override_setting(ces, "matcap_value", &matcap_val);
- override_setting(ces, "ssao_distance", &ssao_distance);
- override_setting(ces, "ssao_factor_cavity", &ssao_factor_cavity);
- override_setting(ces, "ssao_factor_edge", &ssao_factor_edge);
- override_setting(ces, "ssao_attenuation", &ssao_attenuation);
- override_setting(ces, "matcap_icon", &matcap_icon);
- };
-
-
- int index = mat_in_ubo(stl->storage, stl->mat_ubo, pass,
- matcap_rot, matcap_hue, matcap_sat, matcap_val,
- ssao_distance, ssao_factor_cavity, ssao_factor_edge,
- ssao_attenuation, matcap_icon);
-
- return stl->storage->shgrps[index];
-}
-
-static void CLAY_create_cache(CLAY_PassList *passes, CLAY_StorageList *stl, const struct bContext *C)
-{
- SceneLayer *sl = CTX_data_scene_layer(C);
- DRWShadingGroup *clay_shgrp;
- DRWShadingGroup *depth_shgrp;
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
/* Depth Pass */
{
- passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
- depth_shgrp = DRW_shgroup_create(data.depth_sh, passes->depth_pass);
+ psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
}
/* Clay Pass */
{
- passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS);
+ psl->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
stl->storage->ubo_current_id = 0;
+ memset(stl->storage->shgrps, 0, sizeof(DRWShadingGroup *) * MAX_CLAY_MAT);
}
+}
- /* Object Mode */
- {
- DRW_pass_setup_common(&passes->wire_overlay_pass,
- &passes->wire_outline_pass,
- &passes->non_meshes_pass,
- &passes->ob_center_pass);
- }
-
- /* TODO Create hash table of batch based on material id*/
- Object *ob;
- DEG_OBJECT_ITER(sl, CLAY_ENGINE, ob);
- {
- if ((ob->base_flag & BASE_VISIBLED) == 0) {
- continue;
- }
-
- struct Batch *geom;
- //bool do_outlines;
-
- switch (ob->type) {
- case OB_MESH:
- clay_shgrp = CLAY_object_shgrp_get(ob, stl, passes->clay_pass);
- geom = DRW_cache_surface_get(ob);
+static void CLAY_cache_populate(void *vedata, Object *ob)
+{
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
- /* Add everything for now */
- DRW_shgroup_call_add(depth_shgrp, geom, ob->obmat);
+ struct Batch *geom;
+ DRWShadingGroup *clay_shgrp;
- if (clay_shgrp)
- DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
+ if (!DRW_is_object_renderable(ob))
+ return;
- //DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob);
+ IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
+ bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
- //do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
- //DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
+ /* TODO all renderable */
+ if (ob->type == OB_MESH) {
+ geom = DRW_cache_surface_get(ob);
- /* When encountering a new material :
- * - Create new Batch
- * - Initialize Batch
- * - Push it to the hash table
- * - The pass takes care of inserting it
- * next to the same shader calls */
+ /* Depth Prepass */
+ DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
- /* Free hash table */
- break;
- case OB_LAMP:
- case OB_CAMERA:
- case OB_EMPTY:
- default:
- DRW_shgroup_non_meshes(passes->non_meshes_pass, ob);
- break;
- }
-
- DRW_shgroup_object_center(passes->ob_center_pass, ob);
- DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob);
+ /* Shading */
+ clay_shgrp = CLAY_object_shgrp_get(vedata, ob, stl, psl);
+ DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat);
}
- DEG_OBJECT_ITER_END
+}
+
+static void CLAY_cache_finish(void *vedata)
+{
+ CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl;
DRW_uniformbuffer_update(stl->mat_ubo, &stl->storage->mat_storage);
}
-static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context)
+static void CLAY_draw_scene(void *vedata)
{
- /* This function may run for multiple viewports
- * so get the current viewport buffers */
- CLAY_FramebufferList *buffers = NULL;
- CLAY_TextureList *textures = NULL;
- CLAY_PassList *passes = NULL;
- CLAY_StorageList *storage = NULL;
-
- DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes, (void **)&storage);
-
- CLAY_engine_init(storage);
-
- /* TODO : tag to refresh by the deps graph */
- /* ideally only refresh when objects are added/removed */
- /* or render properties / materials change */
-#ifdef WITH_VIEWPORT_CACHE_TEST
- static bool once = false;
-#endif
- if (DRW_viewport_cache_is_dirty()
-#ifdef WITH_VIEWPORT_CACHE_TEST
- && !once
-#endif
- ) {
-#ifdef WITH_VIEWPORT_CACHE_TEST
- once = true;
-#endif
- CLAY_create_cache(passes, storage, context);
- }
- /* Start Drawing */
- DRW_draw_background();
+ CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl;
+ CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
/* Pass 1 : Depth pre-pass */
- DRW_draw_pass(passes->depth_pass);
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
- /* Pass 2 (Optionnal) : Separated Downsampled AO */
- DRW_framebuffer_texture_detach(textures->depth);
- /* TODO */
+ /* Pass 2 : Duplicate depth */
+ /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */
+ DRW_framebuffer_blit(dfbl->default_fb, fbl->dupli_depth, true);
/* Pass 3 : Shading */
- CLAY_ssao_setup();
- DRW_draw_pass(passes->clay_pass);
-
- /* Pass 4 : Overlays */
- DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0);
- //DRW_draw_pass(passes->wire_overlay_pass);
- //DRW_draw_pass(passes->wire_outline_pass);
- DRW_draw_pass(passes->non_meshes_pass);
- DRW_draw_pass(passes->ob_center_pass);
-
- /* Always finish by this */
- DRW_state_reset();
+ DRW_draw_pass(psl->clay_pass);
}
-static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces)
+static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
{
- BLI_assert(ces);
- BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01);
- BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE);
- BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f);
- BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f);
- BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f);
- BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f);
- BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f);
- BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f);
- BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f);
- BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f);
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+
+ BKE_collection_engine_property_add_int(props, "matcap_icon", ICON_MATCAP_01);
+ BKE_collection_engine_property_add_int(props, "type", CLAY_MATCAP_NONE);
+ BKE_collection_engine_property_add_float(props, "matcap_rotation", 0.0f);
+ BKE_collection_engine_property_add_float(props, "matcap_hue", 0.5f);
+ BKE_collection_engine_property_add_float(props, "matcap_saturation", 0.5f);
+ BKE_collection_engine_property_add_float(props, "matcap_value", 0.5f);
+ BKE_collection_engine_property_add_float(props, "ssao_distance", 0.2f);
+ BKE_collection_engine_property_add_float(props, "ssao_attenuation", 1.0f);
+ BKE_collection_engine_property_add_float(props, "ssao_factor_cavity", 1.0f);
+ BKE_collection_engine_property_add_float(props, "ssao_factor_edge", 1.0f);
}
-void clay_engine_free(void)
+static void CLAY_engine_free(void)
{
- /* data.depth_sh Is builtin so it's automaticaly freed */
- if (data.clay_sh) {
- DRW_shader_free(data.clay_sh);
+ if (e_data.clay_sh) {
+ DRW_shader_free(e_data.clay_sh);
}
-
- if (data.matcap_array) {
- DRW_texture_free(data.matcap_array);
+ if (e_data.matcap_array) {
+ DRW_texture_free(e_data.matcap_array);
}
-
- if (data.jitter_tx) {
- DRW_texture_free(data.jitter_tx);
+ if (e_data.jitter_tx) {
+ DRW_texture_free(e_data.jitter_tx);
}
-
- if (data.sampling_tx) {
- DRW_texture_free(data.sampling_tx);
+ if (e_data.sampling_tx) {
+ DRW_texture_free(e_data.sampling_tx);
}
}
+DrawEngineType draw_engine_clay_type = {
+ NULL, NULL,
+ N_("Clay"),
+ &CLAY_engine_init,
+ &CLAY_engine_free,
+ &CLAY_cache_init,
+ &CLAY_cache_populate,
+ &CLAY_cache_finish,
+ NULL,
+ &CLAY_draw_scene
+};
+
RenderEngineType viewport_clay_type = {
NULL, NULL,
CLAY_ENGINE, N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
- NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create,
+ NULL, NULL, NULL, NULL, NULL, NULL, &CLAY_collection_settings_create,
+ &draw_engine_clay_type,
{NULL, NULL, NULL}
};
diff --git a/source/blender/draw/engines/clay/clay.h b/source/blender/draw/engines/clay/clay.h
index 404924be2a1..660ad70ab48 100644
--- a/source/blender/draw/engines/clay/clay.h
+++ b/source/blender/draw/engines/clay/clay.h
@@ -23,14 +23,13 @@
* \ingroup DNA
*/
-#ifndef __ENGINE_CLAY_H__
-#define __ENGINE_CLAY_H__
+#ifndef __CLAY_H__
+#define __CLAY_H__
extern RenderEngineType viewport_clay_type;
-struct RenderEngineSettings *CLAY_render_settings_create(void);
-struct MaterialEngineSettings *CLAY_material_settings_create(void);
+struct IDProperty;
-void clay_engine_free(void);
+struct IDProperty *CLAY_render_settings_create(void);
-#endif /* __ENGINE_CLAY_H__ */ \ No newline at end of file
+#endif /* __CLAY_H__ */
diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
index 7a38db35bcf..35d803dc9ef 100644
--- a/source/blender/draw/engines/clay/shaders/clay_frag.glsl
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -62,13 +62,6 @@ vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
}
}
-/* TODO remove this when switching to geometric normals */
-vec3 calculate_view_space_normal(in vec3 viewposition)
-{
- vec3 normal = cross(normalize(dFdx(viewposition)), dfdy_sign * normalize(dFdy(viewposition)));
- return normalize(normal);
-}
-
#ifdef USE_HSV
void rgb_to_hsv(vec3 rgb, out vec3 outcol)
{
@@ -168,13 +161,6 @@ void main() {
float depth = texture(depthtex, screenco).r;
vec3 position = get_view_space_from_depth(screenco, depth);
- vec3 normal = calculate_view_space_normal(position);
-
- /* Manual Depth test */
- /* Doing this test earlier gives problem with dfdx calculations
- * TODO move this before when we have proper geometric normals */
- if (gl_FragCoord.z > depth + 1e-5)
- discard;
#ifdef USE_ROTATION
/* Rotate texture coordinates */
diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
index 0b598ea0291..557445d5ef9 100644
--- a/source/blender/draw/engines/clay/shaders/clay_vert.glsl
+++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
@@ -1,20 +1,12 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix;
-#if __VERSION__ == 120
-attribute vec3 pos;
-attribute vec3 nor;
-varying vec3 normal;
-#else
in vec3 pos;
in vec3 nor;
out vec3 normal;
-#endif
-
void main()
{
normal = normalize(NormalMatrix * nor);
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
}
-
diff --git a/source/blender/draw/engines/eevee/eevee.c b/source/blender/draw/engines/eevee/eevee.c
new file mode 100644
index 00000000000..d9b1ce596c6
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee.c
+ * \ingroup DNA
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_dynstr.h"
+
+#include "eevee.h"
+#include "eevee_private.h"
+#include "eevee_lut.h"
+
+#define EEVEE_ENGINE "BLENDER_EEVEE"
+
+/* *********** STATIC *********** */
+static struct {
+ struct GPUShader *default_lit;
+ struct GPUShader *depth_sh;
+ struct GPUShader *tonemap;
+ struct GPUTexture *ltc_mat;
+ struct GPUTexture *ltc_mag;
+ float camera_pos[3];
+} e_data = {NULL}; /* Engine data */
+
+extern char datatoc_ltc_lib_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_direct_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_tonemap_frag_glsl[];
+
+/* *********** FUNCTIONS *********** */
+
+static void EEVEE_engine_init(void *vedata)
+{
+ EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
+ EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ DRWFboTexture tex = {&txl->color, DRW_BUF_RGBA_16};
+
+ float *viewport_size = DRW_viewport_size_get();
+ DRW_framebuffer_init(&fbl->main,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &tex, 1);
+
+ if (!e_data.default_lit) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+
+ if (!e_data.default_lit) {
+ char *lib_str = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_vert, datatoc_ltc_lib_glsl);
+ BLI_dynstr_append(ds_vert, datatoc_bsdf_direct_lib_glsl);
+ lib_str = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ e_data.default_lit = DRW_shader_create_with_lib(datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, lib_str, "#define MAX_LIGHT 128\n");
+
+ MEM_freeN(lib_str);
+ }
+
+ if (!e_data.tonemap) {
+ e_data.tonemap = DRW_shader_create_fullscreen(datatoc_tonemap_frag_glsl, NULL);
+ }
+
+ if (!e_data.ltc_mat) {
+ e_data.ltc_mat = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, DRW_TEX_FILTER, ltc_mat_ggx);
+ }
+
+ if (!e_data.ltc_mag) {
+ e_data.ltc_mag = DRW_texture_create_2D(64, 64, DRW_TEX_R_16, DRW_TEX_FILTER, ltc_mag_ggx);
+ }
+
+ if (stl->lights_info == NULL)
+ EEVEE_lights_init(stl);
+
+ // EEVEE_lights_update(stl);
+ {
+ float viewinvmat[4][4];
+ DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV);
+
+ copy_v3_v3(e_data.camera_pos, viewinvmat[3]);
+ }
+}
+
+static void EEVEE_cache_init(void *vedata)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
+
+ psl->depth_pass_cull = DRW_pass_create("Depth Pass Cull", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass_cull);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_EQUAL;
+ psl->pass = DRW_pass_create("Default Light Pass", state);
+
+ stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->pass);
+ DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "light_block", stl->lights_ubo, 0);
+ DRW_shgroup_uniform_int(stl->g_data->default_lit_grp, "light_count", &stl->lights_info->light_count, 1);
+ DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "cameraPos", e_data.camera_pos, 1);
+ DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat, 0);
+ DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMag", e_data.ltc_mag, 1);
+ }
+
+ {
+ /* Final pass : Map HDR color to LDR color.
+ * Write result to the default color buffer */
+ psl->tonemap = DRW_pass_create("Tone Mapping", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.tonemap, psl->tonemap);
+ DRW_shgroup_uniform_buffer(grp, "hdrColorBuf", &txl->color, 0);
+
+ struct Batch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call_add(grp, geom, NULL);
+ }
+
+ EEVEE_lights_cache_init(stl);
+}
+
+static void EEVEE_cache_populate(void *vedata, Object *ob)
+{
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ if (ob->type == OB_MESH) {
+ IDProperty *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
+ bool do_cull = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_backface_culling");
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Depth Prepass */
+ DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
+
+ DRW_shgroup_call_add(stl->g_data->default_lit_grp, geom, ob->obmat);
+ }
+ else if (ob->type == OB_LAMP) {
+ EEVEE_lights_cache_add(stl, ob);
+ }
+}
+
+static void EEVEE_cache_finish(void *vedata)
+{
+ EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+
+ EEVEE_lights_cache_finish(stl);
+}
+
+static void EEVEE_draw_scene(void *vedata)
+{
+ EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ /* Attach depth to the hdr buffer and bind it */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0);
+ DRW_framebuffer_bind(fbl->main);
+
+ /* Clear Depth */
+ /* TODO do background */
+ float clearcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ DRW_framebuffer_clear(true, true, true, clearcol, 1.0f);
+
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->pass);
+
+ /* Restore default framebuffer */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ DRW_framebuffer_bind(dfbl->default_fb);
+
+ DRW_draw_pass(psl->tonemap);
+}
+
+static void EEVEE_engine_free(void)
+{
+ if (e_data.default_lit)
+ DRW_shader_free(e_data.default_lit);
+ if (e_data.tonemap)
+ DRW_shader_free(e_data.tonemap);
+ if (e_data.ltc_mat)
+ DRW_texture_free(e_data.ltc_mat);
+ if (e_data.ltc_mag)
+ DRW_texture_free(e_data.ltc_mag);
+}
+
+static void EEVEE_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
+ // BKE_collection_engine_property_add_int(props, "high_quality_sphere_lamps", false);
+}
+
+DrawEngineType draw_engine_eevee_type = {
+ NULL, NULL,
+ N_("Eevee"),
+ &EEVEE_engine_init,
+ &EEVEE_engine_free,
+ &EEVEE_cache_init,
+ &EEVEE_cache_populate,
+ &EEVEE_cache_finish,
+ &EEVEE_draw_scene,
+ NULL//&EEVEE_draw_scene
+};
+
+RenderEngineType viewport_eevee_type = {
+ NULL, NULL,
+ EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
+ NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
+ &draw_engine_eevee_type,
+ {NULL, NULL, NULL}
+};
+
+
+#undef EEVEE_ENGINE
diff --git a/source/blender/draw/engines/eevee/eevee.h b/source/blender/draw/engines/eevee/eevee.h
new file mode 100644
index 00000000000..8eca5b4d54c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee.h
+ * \ingroup DNA
+ */
+
+#ifndef __EEVEE_H__
+#define __EEVEE_H__
+
+extern RenderEngineType viewport_eevee_type;
+
+#endif /* __EEVEE_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
new file mode 100644
index 00000000000..6a6947bdc3f
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee_lights.c
+ * \ingroup DNA
+ */
+
+#include "DRW_render.h"
+
+#include "eevee_private.h"
+
+#define MAX_LIGHT 210 /* TODO : find size by dividing UBO max size by light data size */
+
+typedef struct EEVEE_Light {
+ float position[3], dist;
+ float color[3], spec;
+ float spotsize, spotblend, radius, shadowid;
+ float rightvec[3], sizex;
+ float upvec[3], sizey;
+ float forwardvec[3], lamptype;
+} EEVEE_Light;
+
+
+void EEVEE_lights_init(EEVEE_StorageList *stl)
+{
+ stl->lights_info = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo");
+ stl->lights_data = MEM_mallocN(sizeof(EEVEE_Light) * MAX_LIGHT, "EEVEE_LightsUboStorage");
+ stl->lights_ref = MEM_mallocN(sizeof(Object *) * MAX_LIGHT, "EEVEE lights_ref");
+ stl->lights_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
+}
+
+void EEVEE_lights_cache_init(EEVEE_StorageList *stl)
+{
+ BLI_listbase_clear(&stl->g_data->lamps);
+ stl->lights_info->light_count = 0;
+}
+
+void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
+{
+ BLI_addtail(&stl->g_data->lamps, BLI_genericNodeN(ob));
+ stl->lights_info->light_count += 1;
+}
+
+void EEVEE_lights_cache_finish(EEVEE_StorageList *stl)
+{
+ int light_ct = stl->lights_info->light_count;
+
+ if (light_ct > MAX_LIGHT) {
+ printf("Too much lamps in the scene !!!\n");
+ stl->lights_info->light_count = MAX_LIGHT;
+ }
+
+ if (light_ct > 0) {
+ int i = 0;
+ for (LinkData *link = stl->g_data->lamps.first; link && i < MAX_LIGHT; link = link->next, i++) {
+ Object *ob = (Object *)link->data;
+ stl->lights_ref[i] = ob;
+ }
+ }
+ BLI_freelistN(&stl->g_data->lamps);
+
+ /* We changed light data so we need to upload it */
+ EEVEE_lights_update(stl);
+}
+
+void EEVEE_lights_update(EEVEE_StorageList *stl)
+{
+ int light_ct = stl->lights_info->light_count;
+
+ /* TODO only update if data changes */
+ /* Update buffer with lamp data */
+ for (int i = 0; i < light_ct; ++i) {
+ EEVEE_Light *evli = stl->lights_data + i;
+ Object *ob = stl->lights_ref[i];
+ Lamp *la = (Lamp *)ob->data;
+ float mat[4][4], scale[3], power;
+
+ /* Position */
+ copy_v3_v3(evli->position, ob->obmat[3]);
+
+ /* Color */
+ evli->color[0] = la->r * la->energy;
+ evli->color[1] = la->g * la->energy;
+ evli->color[2] = la->b * la->energy;
+
+ /* Influence Radius */
+ evli->dist = la->dist;
+
+ /* Vectors */
+ normalize_m4_m4_ex(mat, ob->obmat, scale);
+ copy_v3_v3(evli->forwardvec, mat[2]);
+ normalize_v3(evli->forwardvec);
+ negate_v3(evli->forwardvec);
+
+ copy_v3_v3(evli->rightvec, mat[0]);
+ normalize_v3(evli->rightvec);
+
+ copy_v3_v3(evli->upvec, mat[1]);
+ normalize_v3(evli->upvec);
+
+ /* Spot size & blend */
+ if (la->type == LA_SPOT) {
+ evli->sizex = scale[0] / scale[2];
+ evli->sizey = scale[1] / scale[2];
+ evli->spotsize = cosf(la->spotsize * 0.5f);
+ evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
+ }
+ else if (la->type == LA_AREA) {
+ evli->sizex = MAX2(0.0001f, la->area_size * scale[0] * 0.5f);
+ if (la->area_shape == LA_AREA_RECT) {
+ evli->sizey = MAX2(0.0001f, la->area_sizey * scale[1] * 0.5f);
+ }
+ else {
+ evli->sizey = evli->sizex;
+ }
+ }
+ else {
+ evli->sizex = MAX2(0.001f, la->area_size);
+ }
+
+ /* Make illumination power constant */
+ if (la->type == LA_AREA) {
+ power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) /* 1/(w*h*Pi) */
+ * 80.0f; /* XXX : Empirical, Fit cycles power */
+ }
+ else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
+ power = 1.0f / (4.0f * evli->sizex * evli->sizex * M_PI * M_PI) /* 1/(4*r²*Pi²) */
+ * M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
+
+ /* for point lights (a.k.a radius == 0.0) */
+ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
+ }
+ else {
+ power = 1.0f;
+ }
+ mul_v3_fl(evli->color, power);
+
+ /* Lamp Type */
+ evli->lamptype = (float)la->type;
+ }
+
+ /* Upload buffer to GPU */
+ DRW_uniformbuffer_update(stl->lights_ubo, stl->lights_data);
+}
diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h
new file mode 100644
index 00000000000..4fdfb4c33e2
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut.h
@@ -0,0 +1,2321 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Clement Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file eeveee_lut.h
+ * \ingroup gpu
+ */
+
+#ifndef __EEVEE_LUT_H__
+#define __EEVEE_LUT_H__
+
+static float ltc_mat_ggx[64 * 64 * 4] = {
+ 0.000200, -0.000000, 1.000000, -0.000000, 0.000504, -0.000000, 1.000000, -0.000000, 0.002016,
+ -0.000000, 1.000000, -0.000000, 0.004535, -0.000000, 1.000000, -0.000000, 0.008063, -0.000000,
+ 1.000000, -0.000000, 0.012598, -0.000000, 1.000000, -0.000000, 0.018141, -0.000000, 1.000000,
+ -0.000000, 0.024692, -0.000000, 1.000000, -0.000000, 0.032252, -0.000000, 1.000000, -0.000000,
+ 0.040821, -0.000000, 1.000000, -0.000000, 0.050400, -0.000000, 1.000000, -0.000000, 0.060989,
+ -0.000000, 1.000000, -0.000000, 0.072591, -0.000000, 1.000000, -0.000000, 0.085206, -0.000000,
+ 1.000000, -0.000000, 0.098836, -0.000000, 1.000000, -0.000000, 0.113483, -0.000000, 1.000000,
+ -0.000000, 0.129147, -0.000000, 1.000000, -0.000000, 0.145828, -0.000000, 1.000000, -0.000000,
+ 0.163499, -0.000000, 1.000000, -0.000000, 0.181972, -0.000000, 1.000000, -0.000000, 0.199498,
+ -0.000000, 1.000000, -0.000000, 0.220031, -0.000000, 1.000000, -0.000000, 0.241588, -0.000000,
+ 1.000000, -0.000000, 0.264120, -0.000000, 1.000000, -0.000000, 0.287521, -0.000000, 1.000000,
+ -0.000000, 0.311478, -0.000000, 1.000000, -0.000000, 0.335127, -0.000000, 1.000000, -0.000000,
+ 0.359811, -0.000000, 1.000000, -0.000000, 0.386446, -0.000000, 1.000000, -0.000000, 0.413161,
+ -0.000000, 1.000000, -0.000000, 0.439142, -0.000000, 1.000000, -0.000000, 0.467039, -0.000000,
+ 1.000000, -0.000000, 0.495170, -0.000000, 1.000000, -0.000000, 0.522324, -0.000000, 1.000000,
+ -0.000000, 0.551482, -0.000000, 1.000000, -0.000000, 0.579621, -0.000000, 1.000000, -0.000000,
+ 0.608255, -0.000000, 1.000000, -0.000000, 0.636515, -0.000000, 1.000000, -0.000000, 0.664835,
+ -0.000000, 1.000000, -0.000000, 0.692549, -0.000000, 1.000000, -0.000000, 0.720375, -0.000000,
+ 1.000000, -0.000000, 0.747238, -0.000000, 1.000000, -0.000000, 0.773956, -0.000000, 1.000000,
+ -0.000000, 0.799879, -0.000000, 1.000000, -0.000000, 0.824889, -0.000000, 1.000000, -0.000000,
+ 0.849357, -0.000000, 1.000000, -0.000000, 0.873016, -0.000000, 1.000000, -0.000000, 0.895670,
+ -0.000000, 1.000000, -0.000000, 0.917194, -0.000000, 1.000000, -0.000000, 0.937978, -0.000000,
+ 1.000000, -0.000000, 0.957872, -0.000000, 1.000000, -0.000000, 0.976736, -0.000000, 1.000000,
+ -0.000000, 0.994433, -0.000000, 1.000000, -0.000000, 1.011206, -0.000000, 1.000000, -0.000000,
+ 1.026820, -0.000000, 1.000000, -0.000000, 1.041720, -0.000000, 1.000000, -0.000000, 1.055657,
+ -0.000000, 1.000000, -0.000000, 1.068642, -0.000000, 1.000000, -0.000000, 1.080646, -0.000000,
+ 1.000000, -0.000000, 1.091637, -0.000000, 1.000000, -0.000000, 1.101837, -0.000000, 1.000000,
+ -0.000000, 1.111292, -0.000000, 1.000000, -0.000000, 1.120025, -0.000000, 1.000000, -0.000000,
+ 1.127918, -0.000000, 1.000000, -0.000000, 0.000200, -0.000005, 1.000623, 0.024938, 0.000504,
+ -0.000013, 1.000643, 0.024938, 0.002016, -0.000050, 1.000618, 0.024938, 0.004535, -0.000113,
+ 1.000621, 0.024938, 0.008063, -0.000201, 1.000746, 0.024938, 0.012596, -0.000314, 1.000463,
+ 0.024937, 0.018140, -0.000452, 1.000511, 0.024939, 0.024693, -0.000616, 1.000541, 0.024938,
+ 0.032253, -0.000804, 1.000684, 0.024938, 0.040815, -0.001018, 1.000524, 0.024940, 0.050399,
+ -0.001257, 1.000582, 0.024937, 0.060989, -0.001521, 1.000655, 0.024937, 0.072591, -0.001810,
+ 1.000608, 0.024938, 0.085204, -0.002125, 1.000622, 0.024939, 0.098835, -0.002465, 1.000632,
+ 0.024937, 0.113483, -0.002830, 1.000640, 0.024939, 0.129143, -0.003220, 1.000568, 0.024938,
+ 0.145830, -0.003633, 1.000635, 0.024938, 0.163497, -0.004062, 1.000626, 0.024938, 0.181956,
+ -0.004424, 1.000612, 0.024924, 0.199791, -0.004593, 1.000627, 0.024890, 0.220029, -0.005480,
+ 1.000594, 0.024935, 0.241586, -0.006010, 1.000616, 0.024933, 0.264115, -0.006550, 1.000607,
+ 0.024927, 0.287514, -0.007072, 1.000595, 0.024909, 0.311455, -0.007472, 1.000616, 0.024872,
+ 0.335083, -0.007491, 1.000589, 0.024755, 0.359805, -0.008810, 1.000601, 0.024877, 0.386438,
+ -0.009282, 1.000640, 0.024824, 0.413131, -0.009534, 1.000599, 0.024708, 0.439249, -0.009701,
+ 1.000497, 0.024573, 0.466997, -0.010878, 1.000467, 0.024652, 0.495138, -0.010959, 1.000539,
+ 0.024455, 0.522654, -0.011386, 1.000518, 0.024318, 0.551415, -0.012022, 1.000533, 0.024216,
+ 0.579610, -0.011805, 1.000495, 0.023867, 0.608185, -0.012773, 1.000474, 0.023834, 0.636492,
+ -0.012377, 1.000488, 0.023327, 0.664826, -0.013172, 1.000576, 0.023205, 0.692674, -0.012847,
+ 1.000505, 0.022708, 0.720341, -0.013141, 1.000424, 0.022349, 0.747373, -0.013227, 1.000449,
+ 0.021871, 0.773980, -0.012739, 1.000478, 0.021171, 0.799839, -0.012999, 1.000396, 0.020606,
+ 0.825113, -0.012727, 1.000425, 0.020006, 0.849579, -0.012170, 1.000469, 0.019089, 0.873046,
+ -0.011855, 1.000411, 0.018291, 0.895777, -0.011711, 1.000426, 0.017534, 0.917518, -0.011107,
+ 1.000373, 0.016542, 0.938264, -0.010439, 1.000322, 0.015512, 0.958032, -0.009807, 1.000324,
+ 0.014491, 0.976838, -0.009268, 1.000341, 0.013468, 0.994631, -0.008662, 1.000318, 0.012376,
+ 1.011434, -0.007923, 1.000289, 0.011187, 1.027169, -0.007132, 1.000216, 0.010078, 1.041929,
+ -0.006332, 1.000096, 0.008924, 1.055767, -0.005554, 1.000156, 0.007770, 1.068595, -0.004811,
+ 1.000084, 0.006611, 1.080612, -0.003950, 1.000047, 0.005485, 1.091785, -0.003174, 1.000109,
+ 0.004352, 1.101998, -0.002363, 1.000029, 0.003180, 1.111423, -0.001552, 0.999985, 0.002091,
+ 1.120007, -0.000786, 0.999947, 0.000991, 1.127918, 0.000004, 1.000000, -0.000004, 0.000200,
+ -0.000010, 1.002495, 0.049907, 0.000504, -0.000025, 1.002476, 0.049908, 0.002016, -0.000101,
+ 1.002500, 0.049908, 0.004535, -0.000226, 1.002487, 0.049908, 0.008062, -0.000402, 1.002364,
+ 0.049908, 0.012598, -0.000629, 1.002412, 0.049908, 0.018140, -0.000905, 1.002379, 0.049908,
+ 0.024691, -0.001232, 1.002490, 0.049907, 0.032251, -0.001610, 1.002398, 0.049908, 0.040821,
+ -0.002037, 1.002392, 0.049908, 0.050398, -0.002515, 1.002431, 0.049907, 0.060989, -0.003044,
+ 1.002475, 0.049908, 0.072592, -0.003623, 1.002546, 0.049907, 0.085204, -0.004252, 1.002467,
+ 0.049907, 0.098832, -0.004932, 1.002450, 0.049908, 0.113481, -0.005663, 1.002482, 0.049907,
+ 0.129145, -0.006443, 1.002443, 0.049907, 0.145825, -0.007271, 1.002495, 0.049906, 0.163491,
+ -0.008128, 1.002475, 0.049903, 0.181911, -0.008826, 1.002459, 0.049879, 0.200065, -0.009285,
+ 1.002443, 0.049824, 0.220025, -0.010966, 1.002450, 0.049897, 0.241581, -0.012025, 1.002463,
+ 0.049893, 0.264099, -0.013105, 1.002395, 0.049881, 0.287493, -0.014145, 1.002390, 0.049855,
+ 0.311399, -0.014925, 1.002414, 0.049769, 0.335096, -0.015239, 1.002363, 0.049591, 0.359815,
+ -0.017559, 1.002415, 0.049777, 0.386365, -0.018554, 1.002354, 0.049675, 0.413017, -0.019043,
+ 1.002297, 0.049444, 0.439519, -0.019815, 1.002284, 0.049253, 0.466938, -0.021741, 1.002307,
+ 0.049327, 0.494999, -0.021887, 1.002181, 0.048922, 0.522922, -0.022844, 1.002107, 0.048677,
+ 0.551270, -0.024014, 1.002101, 0.048478, 0.579771, -0.024156, 1.002060, 0.047904, 0.608156,
+ -0.025317, 1.002077, 0.047594, 0.636662, -0.025321, 1.001975, 0.046876, 0.664846, -0.026018,
+ 1.001992, 0.046354, 0.692877, -0.026041, 1.001846, 0.045504, 0.720316, -0.026252, 1.001846,
+ 0.044655, 0.747658, -0.026159, 1.001931, 0.043670, 0.774252, -0.026086, 1.001845, 0.042515,
+ 0.800179, -0.025653, 1.001794, 0.041211, 0.825525, -0.025170, 1.001787, 0.039823, 0.850013,
+ -0.024788, 1.001806, 0.038409, 0.873593, -0.023992, 1.001688, 0.036767, 0.896343, -0.022985,
+ 1.001666, 0.034900, 0.918062, -0.022005, 1.001548, 0.033010, 0.938928, -0.021110, 1.001503,
+ 0.031143, 0.958667, -0.019893, 1.001341, 0.029059, 0.977457, -0.018546, 1.001194, 0.026888,
+ 0.995243, -0.017152, 1.001095, 0.024713, 1.012023, -0.015750, 1.001100, 0.022496, 1.027614,
+ -0.014289, 1.000851, 0.020153, 1.042389, -0.012688, 1.000724, 0.017839, 1.056161, -0.011118,
+ 1.000572, 0.015529, 1.068968, -0.009540, 1.000407, 0.013240, 1.080866, -0.007963, 1.000258,
+ 0.010940, 1.091944, -0.006416, 1.000254, 0.008716, 1.102104, -0.004771, 1.000175, 0.006434,
+ 1.111571, -0.003056, 1.000148, 0.004169, 1.120084, -0.001458, 1.000050, 0.002033, 1.127981,
+ 0.000021, 0.999987, -0.000027, 0.000200, -0.000015, 1.005620, 0.074940, 0.000504, -0.000038,
+ 1.005650, 0.074939, 0.002016, -0.000151, 1.005613, 0.074939, 0.004535, -0.000340, 1.005618,
+ 0.074939, 0.008062, -0.000604, 1.005614, 0.074939, 0.012597, -0.000944, 1.005616, 0.074940,
+ 0.018141, -0.001359, 1.005558, 0.074939, 0.024695, -0.001851, 1.005495, 0.074940, 0.032253,
+ -0.002417, 1.005616, 0.074939, 0.040822, -0.003059, 1.005591, 0.074940, 0.050399, -0.003777,
+ 1.005596, 0.074940, 0.060989, -0.004570, 1.005599, 0.074939, 0.072591, -0.005440, 1.005616,
+ 0.074940, 0.085203, -0.006385, 1.005616, 0.074939, 0.098833, -0.007406, 1.005595, 0.074938,
+ 0.113481, -0.008502, 1.005605, 0.074938, 0.129147, -0.009674, 1.005605, 0.074937, 0.145817,
+ -0.010916, 1.005513, 0.074937, 0.163485, -0.012199, 1.005579, 0.074928, 0.181824, -0.013172,
+ 1.005552, 0.074885, 0.200274, -0.014100, 1.005524, 0.074825, 0.220017, -0.016464, 1.005529,
+ 0.074928, 0.241568, -0.018052, 1.005490, 0.074914, 0.264084, -0.019671, 1.005457, 0.074898,
+ 0.287450, -0.021217, 1.005431, 0.074860, 0.311281, -0.022341, 1.005395, 0.074717, 0.335228,
+ -0.023296, 1.005320, 0.074526, 0.360047, -0.025965, 1.005302, 0.074649, 0.386273, -0.027808,
+ 1.005285, 0.074575, 0.412855, -0.028504, 1.005167, 0.074237, 0.439705, -0.030007, 1.005129,
+ 0.074013, 0.466975, -0.032263, 1.005082, 0.073967, 0.494874, -0.032931, 1.004960, 0.073475,
+ 0.523066, -0.034348, 1.004834, 0.073084, 0.551198, -0.035739, 1.004806, 0.072657, 0.579889,
+ -0.036575, 1.004687, 0.072029, 0.608282, -0.037434, 1.004605, 0.071309, 0.636812, -0.038323,
+ 1.004589, 0.070507, 0.665010, -0.038676, 1.004403, 0.069424, 0.693063, -0.039237, 1.004340,
+ 0.068370, 0.720750, -0.039332, 1.004224, 0.066988, 0.747911, -0.039179, 1.004117, 0.065447,
+ 0.774576, -0.039110, 1.004035, 0.063838, 0.800737, -0.038542, 1.004027, 0.061923, 0.825966,
+ -0.037966, 1.003825, 0.059859, 0.850534, -0.036943, 1.003786, 0.057529, 0.874289, -0.035853,
+ 1.003560, 0.055081, 0.897152, -0.034730, 1.003549, 0.052476, 0.919029, -0.033242, 1.003454,
+ 0.049647, 0.939851, -0.031508, 1.003215, 0.046670, 0.959599, -0.029695, 1.002916, 0.043588,
+ 0.978293, -0.027845, 1.002720, 0.040401, 0.996085, -0.025775, 1.002445, 0.037060, 1.012768,
+ -0.023607, 1.002133, 0.033726, 1.028404, -0.021374, 1.001822, 0.030217, 1.043150, -0.019108,
+ 1.001602, 0.026820, 1.056760, -0.016823, 1.001274, 0.023372, 1.069471, -0.014378, 1.000964,
+ 0.019891, 1.081283, -0.011884, 1.000684, 0.016405, 1.092238, -0.009398, 1.000514, 0.012950,
+ 1.102384, -0.007030, 1.000319, 0.009579, 1.111737, -0.004751, 1.000225, 0.006384, 1.120274,
+ -0.002404, 1.000046, 0.003192, 1.128182, 0.000031, 1.000020, 0.000033, 0.000200, -0.000020,
+ 1.010006, 0.100065, 0.000504, -0.000050, 1.009927, 0.100065, 0.002016, -0.000202, 1.010026,
+ 0.100064, 0.004535, -0.000454, 1.010018, 0.100065, 0.008062, -0.000807, 1.009891, 0.100064,
+ 0.012599, -0.001261, 1.010175, 0.100064, 0.018141, -0.001815, 1.010067, 0.100065, 0.024692,
+ -0.002471, 1.010014, 0.100066, 0.032251, -0.003227, 1.009950, 0.100065, 0.040818, -0.004084,
+ 1.009963, 0.100067, 0.050401, -0.005043, 1.010032, 0.100064, 0.060988, -0.006102, 1.009979,
+ 0.100064, 0.072588, -0.007263, 1.009984, 0.100063, 0.085205, -0.008525, 1.010023, 0.100063,
+ 0.098832, -0.009888, 1.009960, 0.100062, 0.113479, -0.011352, 1.009974, 0.100063, 0.129142,
+ -0.012916, 1.009945, 0.100062, 0.145817, -0.014573, 1.009924, 0.100058, 0.163468, -0.016276,
+ 1.009912, 0.100050, 0.181674, -0.017411, 1.009859, 0.099975, 0.200435, -0.019002, 1.009842,
+ 0.099932, 0.220005, -0.021978, 1.009820, 0.100043, 0.241550, -0.024096, 1.009778, 0.100031,
+ 0.264058, -0.026250, 1.009765, 0.100002, 0.287399, -0.028286, 1.009724, 0.099939, 0.311134,
+ -0.029698, 1.009596, 0.099748, 0.335350, -0.031442, 1.009508, 0.099582, 0.360295, -0.034401,
+ 1.009475, 0.099613, 0.386112, -0.037030, 1.009329, 0.099558, 0.412733, -0.038163, 1.009250,
+ 0.099137, 0.439833, -0.040250, 1.009125, 0.098866, 0.467099, -0.042583, 1.009011, 0.098626,
+ 0.494828, -0.044299, 1.008803, 0.098149, 0.523217, -0.045876, 1.008712, 0.097600, 0.551338,
+ -0.047440, 1.008509, 0.096929, 0.579917, -0.048995, 1.008371, 0.096178, 0.608454, -0.049901,
+ 1.008212, 0.095145, 0.636785, -0.051224, 1.007963, 0.094151, 0.665220, -0.051675, 1.007741,
+ 0.092728, 0.693194, -0.052278, 1.007616, 0.091195, 0.721008, -0.052406, 1.007327, 0.089384,
+ 0.748196, -0.052529, 1.007219, 0.087461, 0.774975, -0.051950, 1.006851, 0.085133, 0.801129,
+ -0.051456, 1.006732, 0.082628, 0.826668, -0.050569, 1.006612, 0.079817, 0.851291, -0.049328,
+ 1.006374, 0.076710, 0.875056, -0.047988, 1.006183, 0.073481, 0.897872, -0.046149, 1.005742,
+ 0.069943, 0.919803, -0.044144, 1.005514, 0.066151, 0.940701, -0.042095, 1.005153, 0.062247,
+ 0.960580, -0.039730, 1.004843, 0.058158, 0.979427, -0.037104, 1.004535, 0.053850, 0.997157,
+ -0.034369, 1.004023, 0.049403, 1.013777, -0.031555, 1.003622, 0.044944, 1.029452, -0.028571,
+ 1.003212, 0.040414, 1.044029, -0.025416, 1.002698, 0.035723, 1.057586, -0.022217, 1.002202,
+ 0.031072, 1.070148, -0.019037, 1.001703, 0.026429, 1.081875, -0.015936, 1.001322, 0.021896,
+ 1.092789, -0.012734, 1.001053, 0.017288, 1.102704, -0.009454, 1.000604, 0.012841, 1.112011,
+ -0.006199, 1.000387, 0.008446, 1.120590, -0.003010, 1.000166, 0.004122, 1.128283, 0.000027,
+ 0.999956, -0.000038, 0.000200, -0.000025, 1.015664, 0.125315, 0.000504, -0.000063, 1.015664,
+ 0.125316, 0.002016, -0.000253, 1.015727, 0.125315, 0.004535, -0.000568, 1.015695, 0.125314,
+ 0.008063, -0.001010, 1.015823, 0.125316, 0.012599, -0.001579, 1.015867, 0.125315, 0.018141,
+ -0.002273, 1.015758, 0.125316, 0.024691, -0.003094, 1.015662, 0.125316, 0.032252, -0.004042,
+ 1.015674, 0.125316, 0.040820, -0.005115, 1.015678, 0.125316, 0.050400, -0.006316, 1.015684,
+ 0.125315, 0.060989, -0.007642, 1.015685, 0.125315, 0.072590, -0.009096, 1.015703, 0.125314,
+ 0.085203, -0.010676, 1.015654, 0.125314, 0.098833, -0.012383, 1.015670, 0.125315, 0.113477,
+ -0.014215, 1.015635, 0.125312, 0.129138, -0.016173, 1.015599, 0.125311, 0.145815, -0.018246,
+ 1.015610, 0.125306, 0.163450, -0.020360, 1.015564, 0.125294, 0.181595, -0.021807, 1.015460,
+ 0.125204, 0.200563, -0.023971, 1.015440, 0.125165, 0.220186, -0.027280, 1.015412, 0.125250,
+ 0.241528, -0.030164, 1.015342, 0.125267, 0.264020, -0.032847, 1.015269, 0.125233, 0.287311,
+ -0.035345, 1.015232, 0.125138, 0.310993, -0.037108, 1.015063, 0.124903, 0.335467, -0.039653,
+ 1.014970, 0.124749, 0.360497, -0.042914, 1.014819, 0.124702, 0.385986, -0.046142, 1.014685,
+ 0.124623, 0.412703, -0.048050, 1.014543, 0.124193, 0.439929, -0.050527, 1.014315, 0.123833,
+ 0.467163, -0.052880, 1.014087, 0.123375, 0.494824, -0.055672, 1.013898, 0.122982, 0.523222,
+ -0.057388, 1.013647, 0.122166, 0.551557, -0.059328, 1.013403, 0.121343, 0.579884, -0.061315,
+ 1.013059, 0.120430, 0.608619, -0.062531, 1.012745, 0.119140, 0.637014, -0.063778, 1.012425,
+ 0.117721, 0.665425, -0.064734, 1.012067, 0.116069, 0.693580, -0.065315, 1.011712, 0.114146,
+ 0.721194, -0.065535, 1.011200, 0.111846, 0.748586, -0.065501, 1.010896, 0.109309, 0.775437,
+ -0.065091, 1.010576, 0.106504, 0.801554, -0.064332, 1.010136, 0.103308, 0.827079, -0.063078,
+ 1.009629, 0.099695, 0.851693, -0.061728, 1.009233, 0.095946, 0.875586, -0.059853, 1.008726,
+ 0.091802, 0.898589, -0.057727, 1.008412, 0.087339, 0.920421, -0.055377, 1.007767, 0.082687,
+ 0.941533, -0.052571, 1.007529, 0.077716, 0.961426, -0.049544, 1.006929, 0.072574, 0.980287,
+ -0.046400, 1.006393, 0.067217, 0.998080, -0.042966, 1.005872, 0.061757, 1.014940, -0.039321,
+ 1.005346, 0.056072, 1.030455, -0.035585, 1.004609, 0.050410, 1.045078, -0.031823, 1.004151,
+ 0.044622, 1.058555, -0.027947, 1.003421, 0.038893, 1.071009, -0.023891, 1.002704, 0.032977,
+ 1.082594, -0.019822, 1.002023, 0.027290, 1.093265, -0.015765, 1.001403, 0.021543, 1.103132,
+ -0.011790, 1.000944, 0.016072, 1.112348, -0.007784, 1.000550, 0.010511, 1.120845, -0.003849,
+ 1.000224, 0.005174, 1.128573, 0.000057, 0.999975, -0.000039, 0.000200, -0.000030, 1.022609,
+ 0.150725, 0.000504, -0.000076, 1.022728, 0.150725, 0.002016, -0.000304, 1.022728, 0.150725,
+ 0.004535, -0.000684, 1.022733, 0.150725, 0.008062, -0.001215, 1.022715, 0.150725, 0.012598,
+ -0.001899, 1.022720, 0.150725, 0.018141, -0.002734, 1.022659, 0.150725, 0.024694, -0.003722,
+ 1.022801, 0.150724, 0.032254, -0.004861, 1.022779, 0.150726, 0.040815, -0.006152, 1.022693,
+ 0.150724, 0.050400, -0.007596, 1.022716, 0.150725, 0.060990, -0.009192, 1.022733, 0.150725,
+ 0.072587, -0.010939, 1.022630, 0.150723, 0.085203, -0.012839, 1.022676, 0.150725, 0.098828,
+ -0.014891, 1.022659, 0.150725, 0.113473, -0.017095, 1.022589, 0.150720, 0.129137, -0.019449,
+ 1.022572, 0.150716, 0.145803, -0.021938, 1.022508, 0.150712, 0.163417, -0.024443, 1.022471,
+ 0.150691, 0.181580, -0.026329, 1.022406, 0.150600, 0.200667, -0.028997, 1.022336, 0.150553,
+ 0.220429, -0.032584, 1.022296, 0.150610, 0.241497, -0.036260, 1.022202, 0.150658, 0.263975,
+ -0.039465, 1.022119, 0.150619, 0.287210, -0.042385, 1.021988, 0.150490, 0.310935, -0.044758,
+ 1.021771, 0.150241, 0.335556, -0.047922, 1.021658, 0.150076, 0.360667, -0.051493, 1.021437,
+ 0.149931, 0.386028, -0.054931, 1.021228, 0.149754, 0.412665, -0.058007, 1.021023, 0.149400,
+ 0.439951, -0.060813, 1.020723, 0.148913, 0.467262, -0.063461, 1.020332, 0.148319, 0.494972,
+ -0.066738, 1.020097, 0.147798, 0.523153, -0.068976, 1.019630, 0.146903, 0.551700, -0.071268,
+ 1.019245, 0.145863, 0.580046, -0.073439, 1.018797, 0.144695, 0.608649, -0.075193, 1.018201,
+ 0.143237, 0.637239, -0.076536, 1.017746, 0.141463, 0.665388, -0.077771, 1.017111, 0.139462,
+ 0.693755, -0.078344, 1.016609, 0.137082, 0.721345, -0.078817, 1.015863, 0.134403, 0.748879,
+ -0.078512, 1.015390, 0.131252, 0.775560, -0.078128, 1.014652, 0.127866, 0.801897, -0.077094,
+ 1.013877, 0.123928, 0.827193, -0.075863, 1.013021, 0.119733, 0.851990, -0.073973, 1.012395,
+ 0.115055, 0.875823, -0.071765, 1.011595, 0.110098, 0.898655, -0.069241, 1.010862, 0.104722,
+ 0.920915, -0.066232, 1.010185, 0.098991, 0.941969, -0.062980, 1.009588, 0.093044, 0.961882,
+ -0.059507, 1.008777, 0.086925, 0.980952, -0.055606, 1.008252, 0.080520, 0.998955, -0.051503,
+ 1.007633, 0.073890, 1.015756, -0.047292, 1.006908, 0.067302, 1.031571, -0.042804, 1.006338,
+ 0.060412, 1.046095, -0.038132, 1.005512, 0.053497, 1.059542, -0.033380, 1.004592, 0.046569,
+ 1.072006, -0.028613, 1.003731, 0.039679, 1.083348, -0.023811, 1.002871, 0.032772, 1.093969,
+ -0.018930, 1.002068, 0.025894, 1.103697, -0.014098, 1.001284, 0.019178, 1.112813, -0.009339,
+ 1.000820, 0.012652, 1.121193, -0.004661, 1.000324, 0.006226, 1.128930, 0.000052, 0.999988,
+ -0.000008, 0.000200, -0.000035, 1.030857, 0.176327, 0.000504, -0.000089, 1.031137, 0.176326,
+ 0.002016, -0.000355, 1.031049, 0.176325, 0.004535, -0.000800, 1.031105, 0.176326, 0.008062,
+ -0.001422, 1.030973, 0.176326, 0.012598, -0.002221, 1.031168, 0.176326, 0.018141, -0.003199,
+ 1.031093, 0.176326, 0.024695, -0.004354, 1.031297, 0.176326, 0.032253, -0.005687, 1.031091,
+ 0.176327, 0.040821, -0.007197, 1.031012, 0.176326, 0.050399, -0.008886, 1.031068, 0.176325,
+ 0.060987, -0.010752, 1.030967, 0.176323, 0.072588, -0.012797, 1.031028, 0.176324, 0.085200,
+ -0.015019, 1.030985, 0.176322, 0.098829, -0.017419, 1.030983, 0.176320, 0.113474, -0.019997,
+ 1.030953, 0.176317, 0.129133, -0.022748, 1.030891, 0.176312, 0.145800, -0.025655, 1.030825,
+ 0.176306, 0.163372, -0.028510, 1.030781, 0.176279, 0.181578, -0.030914, 1.030683, 0.176187,
+ 0.200761, -0.034076, 1.030574, 0.176139, 0.220645, -0.037985, 1.030476, 0.176160, 0.241473,
+ -0.042391, 1.030384, 0.176238, 0.263922, -0.046105, 1.030241, 0.176175, 0.287074, -0.049390,
+ 1.030049, 0.176013, 0.310915, -0.052511, 1.029839, 0.175776, 0.335604, -0.056236, 1.029608,
+ 0.175578, 0.360775, -0.060118, 1.029355, 0.175359, 0.386196, -0.063907, 1.029052, 0.175083,
+ 0.412599, -0.067997, 1.028766, 0.174791, 0.439916, -0.071088, 1.028326, 0.174174, 0.467444,
+ -0.074247, 1.027890, 0.173487, 0.495132, -0.077728, 1.027374, 0.172774, 0.523117, -0.080822,
+ 1.026763, 0.171824, 0.551783, -0.083228, 1.026205, 0.170554, 0.580234, -0.085682, 1.025614,
+ 0.169090, 0.608568, -0.087860, 1.024668, 0.167468, 0.637357, -0.089346, 1.023939, 0.165283,
+ 0.665507, -0.090704, 1.022946, 0.162966, 0.693704, -0.091388, 1.022010, 0.160131, 0.721396,
+ -0.091783, 1.021085, 0.156957, 0.748676, -0.091688, 1.019894, 0.153292, 0.775370, -0.090992,
+ 1.018608, 0.149158, 0.801547, -0.089881, 1.017646, 0.144551, 0.827013, -0.088267, 1.016355,
+ 0.139614, 0.851708, -0.086132, 1.015446, 0.134026, 0.875652, -0.083707, 1.014321, 0.128101,
+ 0.898703, -0.080619, 1.013454, 0.121841, 0.920904, -0.077280, 1.012634, 0.115379, 0.942077,
+ -0.073484, 1.011770, 0.108355, 0.962245, -0.069252, 1.010894, 0.101153, 0.981385, -0.064807,
+ 1.010114, 0.093666, 0.999379, -0.060080, 1.009294, 0.086007, 1.016494, -0.055007, 1.008591,
+ 0.078194, 1.032357, -0.049760, 1.007821, 0.070328, 1.047061, -0.044468, 1.006871, 0.062358,
+ 1.060675, -0.038960, 1.006062, 0.054279, 1.073032, -0.033343, 1.004911, 0.046158, 1.084293,
+ -0.027699, 1.003791, 0.038111, 1.094724, -0.022130, 1.002744, 0.030239, 1.104302, -0.016508,
+ 1.001815, 0.022397, 1.113290, -0.010846, 1.001083, 0.014747, 1.121649, -0.005294, 1.000490,
+ 0.007234, 1.129230, 0.000071, 0.999975, -0.000053, 0.000200, -0.000040, 1.040431, 0.202155,
+ 0.000504, -0.000102, 1.040912, 0.202154, 0.002016, -0.000407, 1.041328, 0.202152, 0.004535,
+ -0.000917, 1.040877, 0.202154, 0.008063, -0.001630, 1.040867, 0.202153, 0.012598, -0.002547,
+ 1.040870, 0.202153, 0.018140, -0.003667, 1.040808, 0.202153, 0.024692, -0.004991, 1.040861,
+ 0.202153, 0.032252, -0.006519, 1.040861, 0.202153, 0.040822, -0.008252, 1.040864, 0.202153,
+ 0.050397, -0.010187, 1.040717, 0.202151, 0.060988, -0.012327, 1.040791, 0.202152, 0.072582,
+ -0.014669, 1.040640, 0.202149, 0.085198, -0.017217, 1.040716, 0.202147, 0.098827, -0.019968,
+ 1.040748, 0.202141, 0.113467, -0.022921, 1.040632, 0.202142, 0.129129, -0.026074, 1.040606,
+ 0.202137, 0.145793, -0.029399, 1.040566, 0.202127, 0.163294, -0.032524, 1.040459, 0.202078,
+ 0.181589, -0.035552, 1.040315, 0.201996, 0.200844, -0.039208, 1.040221, 0.201948, 0.220835,
+ -0.043489, 1.040047, 0.201945, 0.241471, -0.048523, 1.039921, 0.202031, 0.263854, -0.052764,
+ 1.039756, 0.201957, 0.286935, -0.056387, 1.039497, 0.201743, 0.310902, -0.060338, 1.039252,
+ 0.201531, 0.335642, -0.064594, 1.038954, 0.201286, 0.360859, -0.068772, 1.038582, 0.200983,
+ 0.386419, -0.073086, 1.038160, 0.200651, 0.412588, -0.077887, 1.037724, 0.200343, 0.439836,
+ -0.081391, 1.037182, 0.199618, 0.467538, -0.085121, 1.036602, 0.198839, 0.495286, -0.088718,
+ 1.035893, 0.197895, 0.523231, -0.092514, 1.035121, 0.196887, 0.551730, -0.095238, 1.034127,
+ 0.195390, 0.580302, -0.097949, 1.033131, 0.193668, 0.608559, -0.100418, 1.031962, 0.191773,
+ 0.637224, -0.102129, 1.030838, 0.189319, 0.665597, -0.103578, 1.029511, 0.186529, 0.693535,
+ -0.104652, 1.028263, 0.183303, 0.721325, -0.104766, 1.026611, 0.179497, 0.748384, -0.104717,
+ 1.025128, 0.175283, 0.775058, -0.103846, 1.023385, 0.170493, 0.801387, -0.102728, 1.022236,
+ 0.165187, 0.826412, -0.100679, 1.019908, 0.159362, 0.851314, -0.098451, 1.018839, 0.153059,
+ 0.875100, -0.095363, 1.017306, 0.146284, 0.898280, -0.092008, 1.016151, 0.138975, 0.920450,
+ -0.088095, 1.014880, 0.131361, 0.941727, -0.083690, 1.013556, 0.123417, 0.962308, -0.079077,
+ 1.012998, 0.115201, 0.981364, -0.073894, 1.011841, 0.106711, 0.999798, -0.068435, 1.011021,
+ 0.098063, 1.016983, -0.062830, 1.010194, 0.089183, 1.033039, -0.056914, 1.009292, 0.080190,
+ 1.047994, -0.050721, 1.008474, 0.071010, 1.061580, -0.044454, 1.007386, 0.061867, 1.074023,
+ -0.038145, 1.006135, 0.052711, 1.085470, -0.031679, 1.004890, 0.043595, 1.095673, -0.025157,
+ 1.003627, 0.034506, 1.105000, -0.018702, 1.002331, 0.025468, 1.113795, -0.012458, 1.001278,
+ 0.016834, 1.122012, -0.006169, 1.000548, 0.008265, 1.129683, 0.000078, 0.999988, -0.000072,
+ 0.000200, -0.000046, 1.052496, 0.228243, 0.000504, -0.000115, 1.052079, 0.228243, 0.002016,
+ -0.000460, 1.052079, 0.228241, 0.004535, -0.001035, 1.052091, 0.228242, 0.008062, -0.001840,
+ 1.051962, 0.228242, 0.012598, -0.002875, 1.052087, 0.228242, 0.018141, -0.004140, 1.052088,
+ 0.228242, 0.024692, -0.005636, 1.052096, 0.228239, 0.032251, -0.007361, 1.052029, 0.228243,
+ 0.040820, -0.009316, 1.052038, 0.228241, 0.050399, -0.011501, 1.052042, 0.228239, 0.060990,
+ -0.013917, 1.052046, 0.228238, 0.072586, -0.016562, 1.051990, 0.228236, 0.085198, -0.019437,
+ 1.051946, 0.228234, 0.098824, -0.022542, 1.051879, 0.228229, 0.113467, -0.025875, 1.051841,
+ 0.228227, 0.129121, -0.029430, 1.051724, 0.228219, 0.145780, -0.033170, 1.051672, 0.228205,
+ 0.163222, -0.036567, 1.051556, 0.228143, 0.181604, -0.040245, 1.051382, 0.228069, 0.200913,
+ -0.044395, 1.051230, 0.228010, 0.221005, -0.049088, 1.051062, 0.227988, 0.241667, -0.054506,
+ 1.050881, 0.228044, 0.263777, -0.059437, 1.050643, 0.227986, 0.286841, -0.063590, 1.050312,
+ 0.227755, 0.310879, -0.068224, 1.050009, 0.227525, 0.335650, -0.072986, 1.049597, 0.227253,
+ 0.360869, -0.077435, 1.049121, 0.226845, 0.386609, -0.082385, 1.048587, 0.226466, 0.412742,
+ -0.087570, 1.047987, 0.226059, 0.439789, -0.091929, 1.047308, 0.225331, 0.467558, -0.096038,
+ 1.046423, 0.224409, 0.495406, -0.099938, 1.045481, 0.223288, 0.523417, -0.104050, 1.044512,
+ 0.222066, 0.551755, -0.107503, 1.043408, 0.220487, 0.580468, -0.110234, 1.042016, 0.218451,
+ 0.608904, -0.112993, 1.040535, 0.216200, 0.637230, -0.115173, 1.038934, 0.213458, 0.665566,
+ -0.116433, 1.036961, 0.210158, 0.693413, -0.117589, 1.035130, 0.206457, 0.721025, -0.117885,
+ 1.033080, 0.202197, 0.748054, -0.117606, 1.030752, 0.197296, 0.774631, -0.116771, 1.028608,
+ 0.191813, 0.800677, -0.115194, 1.026350, 0.185691, 0.826062, -0.113138, 1.024472, 0.179053,
+ 0.850590, -0.110359, 1.022174, 0.171839, 0.874550, -0.107072, 1.020381, 0.164067, 0.897567,
+ -0.103268, 1.018777, 0.155959, 0.919609, -0.098794, 1.016886, 0.147320, 0.941177, -0.094067,
+ 1.015880, 0.138365, 0.961752, -0.088670, 1.014616, 0.129051, 0.981518, -0.082965, 1.013807,
+ 0.119515, 0.999880, -0.076971, 1.012793, 0.109897, 1.017370, -0.070518, 1.011894, 0.099872,
+ 1.033661, -0.063830, 1.010943, 0.089883, 1.048672, -0.057040, 1.009802, 0.079691, 1.062479,
+ -0.049917, 1.008670, 0.069458, 1.075052, -0.042735, 1.007429, 0.059191, 1.086371, -0.035513,
+ 1.005991, 0.048894, 1.096623, -0.028359, 1.004468, 0.038770, 1.105871, -0.021111, 1.002927,
+ 0.028745, 1.114481, -0.013908, 1.001728, 0.018884, 1.122610, -0.006843, 1.000740, 0.009264,
+ 1.130165, 0.000062, 0.999983, -0.000006, 0.000200, -0.000051, 1.064931, 0.254630, 0.000504,
+ -0.000128, 1.064668, 0.254630, 0.002016, -0.000513, 1.064794, 0.254630, 0.004535, -0.001155,
+ 1.064851, 0.254630, 0.008063, -0.002053, 1.064966, 0.254630, 0.012598, -0.003208, 1.064840,
+ 0.254630, 0.018140, -0.004619, 1.064602, 0.254631, 0.024695, -0.006288, 1.064965, 0.254632,
+ 0.032251, -0.008211, 1.064795, 0.254630, 0.040821, -0.010393, 1.064802, 0.254628, 0.050398,
+ -0.012830, 1.064758, 0.254627, 0.060987, -0.015525, 1.064731, 0.254625, 0.072584, -0.018474,
+ 1.064615, 0.254621, 0.085199, -0.021682, 1.064672, 0.254619, 0.098826, -0.025144, 1.064630,
+ 0.254613, 0.113465, -0.028860, 1.064515, 0.254606, 0.129119, -0.032823, 1.064416, 0.254598,
+ 0.145767, -0.036969, 1.064347, 0.254579, 0.163190, -0.040754, 1.064132, 0.254506, 0.181622,
+ -0.044989, 1.063951, 0.254437, 0.200981, -0.049642, 1.063745, 0.254370, 0.221145, -0.054776,
+ 1.063547, 0.254324, 0.241896, -0.060538, 1.063289, 0.254346, 0.263684, -0.066113, 1.063013,
+ 0.254296, 0.286796, -0.070925, 1.062625, 0.254059, 0.310867, -0.076187, 1.062216, 0.253817,
+ 0.335644, -0.081406, 1.061703, 0.253481, 0.360917, -0.086336, 1.061066, 0.253005, 0.386786,
+ -0.091790, 1.060454, 0.252558, 0.412921, -0.097230, 1.059568, 0.252008, 0.439722, -0.102574,
+ 1.058706, 0.251323, 0.467559, -0.106972, 1.057682, 0.250239, 0.495605, -0.111329, 1.056612,
+ 0.248944, 0.523589, -0.115561, 1.055101, 0.247471, 0.551787, -0.119732, 1.053745, 0.245777,
+ 0.580426, -0.122711, 1.051829, 0.243448, 0.608778, -0.125436, 1.049642, 0.240769, 0.637069,
+ -0.127993, 1.047749, 0.237739, 0.665251, -0.129448, 1.045244, 0.233928, 0.692977, -0.130408,
+ 1.042279, 0.229640, 0.720346, -0.130931, 1.039693, 0.224829, 0.747365, -0.130392, 1.036675,
+ 0.219144, 0.773734, -0.129540, 1.033719, 0.212965, 0.799578, -0.127689, 1.030774, 0.206047,
+ 0.825002, -0.125456, 1.028551, 0.198576, 0.849564, -0.122291, 1.025800, 0.190471, 0.873412,
+ -0.118720, 1.023657, 0.181739, 0.896628, -0.114323, 1.021381, 0.172586, 0.918952, -0.109587,
+ 1.019674, 0.162914, 0.940602, -0.104093, 1.018126, 0.153039, 0.960917, -0.098187, 1.016339,
+ 0.142774, 0.980911, -0.091963, 1.015440, 0.132316, 0.999686, -0.085159, 1.014377, 0.121453,
+ 1.017538, -0.078139, 1.013498, 0.110527, 1.033918, -0.070797, 1.012332, 0.099437, 1.049390,
+ -0.063129, 1.011368, 0.088157, 1.063402, -0.055354, 1.010111, 0.076951, 1.076096, -0.047522,
+ 1.008774, 0.065616, 1.087562, -0.039447, 1.007202, 0.054310, 1.097591, -0.031359, 1.005346,
+ 0.042948, 1.106782, -0.023393, 1.003710, 0.031799, 1.115234, -0.015461, 1.002116, 0.020943,
+ 1.123166, -0.007589, 1.000858, 0.010288, 1.130796, 0.000104, 1.000032, -0.000024, 0.000200,
+ -0.000056, 1.078780, 0.281356, 0.000504, -0.000142, 1.079271, 0.281355, 0.002015, -0.000567,
+ 1.078635, 0.281355, 0.004535, -0.001276, 1.079164, 0.281356, 0.008064, -0.002269, 1.079300,
+ 0.281355, 0.012598, -0.003544, 1.079149, 0.281355, 0.018143, -0.005104, 1.079329, 0.281355,
+ 0.024691, -0.006947, 1.079073, 0.281353, 0.032254, -0.009074, 1.079253, 0.281354, 0.040822,
+ -0.011484, 1.079176, 0.281353, 0.050399, -0.014177, 1.079057, 0.281349, 0.060987, -0.017153,
+ 1.079007, 0.281347, 0.072586, -0.020412, 1.078998, 0.281343, 0.085203, -0.023956, 1.078962,
+ 0.281336, 0.098823, -0.027778, 1.078839, 0.281332, 0.113464, -0.031882, 1.078783, 0.281325,
+ 0.129114, -0.036255, 1.078633, 0.281315, 0.145748, -0.040790, 1.078545, 0.281287, 0.163179,
+ -0.045024, 1.078311, 0.281208, 0.181649, -0.049791, 1.078135, 0.281137, 0.201042, -0.054953,
+ 1.077845, 0.281063, 0.221267, -0.060551, 1.077576, 0.281006, 0.242114, -0.066663, 1.077257,
+ 0.280978, 0.263568, -0.072771, 1.076897, 0.280925, 0.286744, -0.078349, 1.076405, 0.280689,
+ 0.310840, -0.084201, 1.075898, 0.280418, 0.335612, -0.089846, 1.075287, 0.280020, 0.360975,
+ -0.095394, 1.074482, 0.279513, 0.386932, -0.101290, 1.073617, 0.278961, 0.413171, -0.107042,
+ 1.072719, 0.278283, 0.439886, -0.113083, 1.071698, 0.277547, 0.467535, -0.118010, 1.070213,
+ 0.276311, 0.495701, -0.122793, 1.068857, 0.274867, 0.523772, -0.127278, 1.067037, 0.273153,
+ 0.551849, -0.131671, 1.064923, 0.271176, 0.580338, -0.135293, 1.062749, 0.268626, 0.608771,
+ -0.138065, 1.059944, 0.265569, 0.636756, -0.140565, 1.056851, 0.262054, 0.664574, -0.142434,
+ 1.053461, 0.257807, 0.692151, -0.143237, 1.049910, 0.252930, 0.719376, -0.143717, 1.046426,
+ 0.247414, 0.745852, -0.143117, 1.042377, 0.241001, 0.772300, -0.141975, 1.038789, 0.233797,
+ 0.798050, -0.140114, 1.035290, 0.226218, 0.823370, -0.137379, 1.032374, 0.217785, 0.847735,
+ -0.134119, 1.028853, 0.208748, 0.871897, -0.129985, 1.026395, 0.198877, 0.894950, -0.125324,
+ 1.023787, 0.188803, 0.917909, -0.120007, 1.022073, 0.178493, 0.939567, -0.114099, 1.020098,
+ 0.167466, 0.960534, -0.107748, 1.018851, 0.156223, 0.980423, -0.100748, 1.017362, 0.144716,
+ 0.999334, -0.093494, 1.015961, 0.133028, 1.017561, -0.085728, 1.015059, 0.120953, 1.034225,
+ -0.077627, 1.013888, 0.108943, 1.049937, -0.069375, 1.012898, 0.096678, 1.064265, -0.060807,
+ 1.011635, 0.084350, 1.077188, -0.052052, 1.010095, 0.071964, 1.088637, -0.043304, 1.008399,
+ 0.059531, 1.098766, -0.034458, 1.006397, 0.047134, 1.107697, -0.025637, 1.004354, 0.034887,
+ 1.116055, -0.016932, 1.002611, 0.022948, 1.123819, -0.008437, 1.001023, 0.011386, 1.131333,
+ 0.000087, 0.999952, -0.000097, 0.000200, -0.000062, 1.095622, 0.308458, 0.000504, -0.000155,
+ 1.094863, 0.308458, 0.002016, -0.000622, 1.095169, 0.308458, 0.004535, -0.001399, 1.095156,
+ 0.308458, 0.008063, -0.002487, 1.095413, 0.308455, 0.012598, -0.003886, 1.095147, 0.308458,
+ 0.018141, -0.005596, 1.095150, 0.308457, 0.024692, -0.007616, 1.095140, 0.308457, 0.032252,
+ -0.009947, 1.095098, 0.308456, 0.040822, -0.012589, 1.095096, 0.308453, 0.050399, -0.015541,
+ 1.095070, 0.308451, 0.060985, -0.018803, 1.094922, 0.308448, 0.072583, -0.022375, 1.094902,
+ 0.308444, 0.085197, -0.026258, 1.094882, 0.308438, 0.098822, -0.030448, 1.094775, 0.308429,
+ 0.113460, -0.034944, 1.094641, 0.308419, 0.129112, -0.039731, 1.094530, 0.308403, 0.145711,
+ -0.044610, 1.094332, 0.308365, 0.163178, -0.049362, 1.094149, 0.308285, 0.181679, -0.054666,
+ 1.093876, 0.308210, 0.201109, -0.060336, 1.093603, 0.308132, 0.221388, -0.066414, 1.093250,
+ 0.308047, 0.242315, -0.072881, 1.092835, 0.307985, 0.263651, -0.079453, 1.092391, 0.307902,
+ 0.286720, -0.085882, 1.091866, 0.307688, 0.310817, -0.092274, 1.091225, 0.307379, 0.335562,
+ -0.098306, 1.090346, 0.306906, 0.361043, -0.104572, 1.089423, 0.306374, 0.387051, -0.110843,
+ 1.088437, 0.305710, 0.413405, -0.117062, 1.087228, 0.304906, 0.440122, -0.123501, 1.085879,
+ 0.304017, 0.467522, -0.129245, 1.084197, 0.302783, 0.495721, -0.134285, 1.082284, 0.301104,
+ 0.523925, -0.139143, 1.080109, 0.299142, 0.551814, -0.143638, 1.077043, 0.296825, 0.579878,
+ -0.147774, 1.074071, 0.294071, 0.608316, -0.150724, 1.070621, 0.290519, 0.636059, -0.153168,
+ 1.066390, 0.286424, 0.663481, -0.155139, 1.062069, 0.281559, 0.690753, -0.155944, 1.057211,
+ 0.276024, 0.717767, -0.156176, 1.052682, 0.269622, 0.743937, -0.155783, 1.047747, 0.262532,
+ 0.770214, -0.154245, 1.043510, 0.254609, 0.795542, -0.152192, 1.039121, 0.246007, 0.821099,
+ -0.149256, 1.035962, 0.236663, 0.845452, -0.145605, 1.032320, 0.226751, 0.869780, -0.141186,
+ 1.029390, 0.216165, 0.893141, -0.136137, 1.026485, 0.204937, 0.916034, -0.130332, 1.024389,
+ 0.193624, 0.938089, -0.124040, 1.022270, 0.181756, 0.959488, -0.117011, 1.020457, 0.169339,
+ 0.979594, -0.109617, 1.018871, 0.156875, 0.998912, -0.101562, 1.017533, 0.144288, 1.017100,
+ -0.093164, 1.016445, 0.131370, 1.034413, -0.084488, 1.015453, 0.118322, 1.050347, -0.075377,
+ 1.014259, 0.104963, 1.064958, -0.066108, 1.013057, 0.091722, 1.078045, -0.056702, 1.011491,
+ 0.078231, 1.089749, -0.047106, 1.009662, 0.064797, 1.099831, -0.037467, 1.007417, 0.051315,
+ 1.108789, -0.027990, 1.005144, 0.038064, 1.116865, -0.018464, 1.002925, 0.025008, 1.124609,
+ -0.009068, 1.001221, 0.012250, 1.132040, 0.000093, 0.999984, -0.000071, 0.000200, -0.000067,
+ 1.112554, 0.335981, 0.000504, -0.000169, 1.112660, 0.335981, 0.002016, -0.000677, 1.112827,
+ 0.335981, 0.004533, -0.001523, 1.112147, 0.335982, 0.008063, -0.002709, 1.112882, 0.335979,
+ 0.012598, -0.004233, 1.112891, 0.335980, 0.018141, -0.006095, 1.112882, 0.335980, 0.024693,
+ -0.008296, 1.112877, 0.335978, 0.032252, -0.010834, 1.112860, 0.335976, 0.040824, -0.013713,
+ 1.112965, 0.335974, 0.050398, -0.016927, 1.112753, 0.335971, 0.060991, -0.020482, 1.112826,
+ 0.335970, 0.072587, -0.024371, 1.112676, 0.335962, 0.085199, -0.028597, 1.112593, 0.335955,
+ 0.098822, -0.033159, 1.112453, 0.335943, 0.113461, -0.038052, 1.112329, 0.335930, 0.129108,
+ -0.043255, 1.112144, 0.335910, 0.145665, -0.048412, 1.111905, 0.335857, 0.163185, -0.053786,
+ 1.111668, 0.335781, 0.181710, -0.059608, 1.111345, 0.335696, 0.201166, -0.065794, 1.110979,
+ 0.335606, 0.221489, -0.072361, 1.110553, 0.335505, 0.242471, -0.079184, 1.110112, 0.335396,
+ 0.263900, -0.086213, 1.109584, 0.335271, 0.286688, -0.093491, 1.108927, 0.335089, 0.310773,
+ -0.100406, 1.108091, 0.334737, 0.335573, -0.106987, 1.107169, 0.334208, 0.361117, -0.113844,
+ 1.106097, 0.333600, 0.387175, -0.120463, 1.104826, 0.332828, 0.413665, -0.127245, 1.103415,
+ 0.331929, 0.440386, -0.133927, 1.101632, 0.330851, 0.467527, -0.140496, 1.099563, 0.329538,
+ 0.495630, -0.145874, 1.096956, 0.327618, 0.523864, -0.150997, 1.094201, 0.325390, 0.551705,
+ -0.155713, 1.090342, 0.322688, 0.579383, -0.159993, 1.086010, 0.319483, 0.607301, -0.163238,
+ 1.081226, 0.315522, 0.634873, -0.165667, 1.076065, 0.310840, 0.662028, -0.167606, 1.070466,
+ 0.305377, 0.688755, -0.168626, 1.064601, 0.299056, 0.715612, -0.168578, 1.059269, 0.291963,
+ 0.741604, -0.167961, 1.053648, 0.284018, 0.767757, -0.166439, 1.048928, 0.275474, 0.793264,
+ -0.164023, 1.044343, 0.266056, 0.818165, -0.160965, 1.039909, 0.255750, 0.843255, -0.156896,
+ 1.036180, 0.244843, 0.867249, -0.152262, 1.032303, 0.233464, 0.890994, -0.146655, 1.029365,
+ 0.221128, 0.913829, -0.140574, 1.026607, 0.208554, 0.936508, -0.133640, 1.024512, 0.195772,
+ 0.957720, -0.126220, 1.022421, 0.182420, 0.978940, -0.118164, 1.021293, 0.168852, 0.998285,
+ -0.109558, 1.019444, 0.155261, 1.016764, -0.100562, 1.017825, 0.141395, 1.034387, -0.091064,
+ 1.016996, 0.127311, 1.050916, -0.081468, 1.015945, 0.113089, 1.065652, -0.071463, 1.014547,
+ 0.098879, 1.079155, -0.061240, 1.013066, 0.084468, 1.090822, -0.050980, 1.010788, 0.069940,
+ 1.101100, -0.040549, 1.008563, 0.055475, 1.109824, -0.030101, 1.005950, 0.041033, 1.117828,
+ -0.019884, 1.003453, 0.027022, 1.125443, -0.009900, 1.001484, 0.013306, 1.132869, 0.000094,
+ 1.000004, -0.000046, 0.000200, -0.000073, 1.132849, 0.363970, 0.000504, -0.000183, 1.132155,
+ 0.363969, 0.002016, -0.000734, 1.132516, 0.363969, 0.004535, -0.001651, 1.132256, 0.363969,
+ 0.008062, -0.002934, 1.132318, 0.363966, 0.012597, -0.004585, 1.132386, 0.363968, 0.018141,
+ -0.006602, 1.132457, 0.363967, 0.024693, -0.008987, 1.132511, 0.363967, 0.032252, -0.011737,
+ 1.132488, 0.363965, 0.040819, -0.014853, 1.132241, 0.363959, 0.050398, -0.018336, 1.132372,
+ 0.363958, 0.060988, -0.022185, 1.132373, 0.363954, 0.072582, -0.026396, 1.132137, 0.363943,
+ 0.085195, -0.030973, 1.132071, 0.363935, 0.098822, -0.035913, 1.131978, 0.363922, 0.113461,
+ -0.041209, 1.131801, 0.363905, 0.129116, -0.046833, 1.131535, 0.363867, 0.145640, -0.052346,
+ 1.131290, 0.363814, 0.163199, -0.058275, 1.131046, 0.363734, 0.181742, -0.064623, 1.130671,
+ 0.363642, 0.201227, -0.071336, 1.130224, 0.363539, 0.221587, -0.078396, 1.129758, 0.363419,
+ 0.242625, -0.085545, 1.129213, 0.363256, 0.264183, -0.093110, 1.128549, 0.363097, 0.286668,
+ -0.101206, 1.127767, 0.362939, 0.310745, -0.108586, 1.126796, 0.362516, 0.335602, -0.115827,
+ 1.125686, 0.361953, 0.361202, -0.123212, 1.124451, 0.361275, 0.387298, -0.130294, 1.122861,
+ 0.360376, 0.413918, -0.137553, 1.121154, 0.359362, 0.440680, -0.144577, 1.118825, 0.358069,
+ 0.467667, -0.151558, 1.116002, 0.356581, 0.495449, -0.157621, 1.112778, 0.354531, 0.523514,
+ -0.162844, 1.108842, 0.351915, 0.551250, -0.167744, 1.104075, 0.348797, 0.578629, -0.172132,
+ 1.098733, 0.345222, 0.605757, -0.175733, 1.092224, 0.340665, 0.633392, -0.178109, 1.086201,
+ 0.335286, 0.660783, -0.180009, 1.080110, 0.329286, 0.687219, -0.181105, 1.073419, 0.322319,
+ 0.713873, -0.181046, 1.067410, 0.314616, 0.740094, -0.180219, 1.061414, 0.306014, 0.765233,
+ -0.178559, 1.055287, 0.296704, 0.790885, -0.175806, 1.049727, 0.286394, 0.815464, -0.172354,
+ 1.044519, 0.275189, 0.840259, -0.168048, 1.040375, 0.263441, 0.864285, -0.162904, 1.036010,
+ 0.250918, 0.888806, -0.157194, 1.033525, 0.237611, 0.911682, -0.150486, 1.029490, 0.223809,
+ 0.934481, -0.143212, 1.026778, 0.209705, 0.956337, -0.135233, 1.024632, 0.195281, 0.977380,
+ -0.126650, 1.022737, 0.180878, 0.997427, -0.117552, 1.021110, 0.166112, 1.016666, -0.107814,
+ 1.019869, 0.151231, 1.034337, -0.097814, 1.018543, 0.136375, 1.051082, -0.087330, 1.017476,
+ 0.121187, 1.066326, -0.076614, 1.016083, 0.106043, 1.079897, -0.065793, 1.014227, 0.090566,
+ 1.092136, -0.054654, 1.012334, 0.074988, 1.102315, -0.043516, 1.009627, 0.059577, 1.111105,
+ -0.032509, 1.006808, 0.044202, 1.118861, -0.021381, 1.003917, 0.028995, 1.126363, -0.010489,
+ 1.001670, 0.014269, 1.133598, 0.000083, 0.999989, -0.000035, 0.000200, -0.000079, 1.155026,
+ 0.392470, 0.000504, -0.000198, 1.154184, 0.392469, 0.002016, -0.000791, 1.153990, 0.392469,
+ 0.004535, -0.001780, 1.154045, 0.392469, 0.008063, -0.003164, 1.154007, 0.392466, 0.012598,
+ -0.004944, 1.154022, 0.392469, 0.018141, -0.007119, 1.154015, 0.392468, 0.024692, -0.009690,
+ 1.154017, 0.392466, 0.032254, -0.012656, 1.154069, 0.392465, 0.040826, -0.016018, 1.153980,
+ 0.392459, 0.050399, -0.019771, 1.153911, 0.392456, 0.060987, -0.023919, 1.153860, 0.392447,
+ 0.072588, -0.028461, 1.153777, 0.392442, 0.085197, -0.033393, 1.153582, 0.392428, 0.098822,
+ -0.038716, 1.153434, 0.392412, 0.113462, -0.044422, 1.153271, 0.392390, 0.129101, -0.050455,
+ 1.153019, 0.392359, 0.145642, -0.056392, 1.152721, 0.392283, 0.163223, -0.062859, 1.152404,
+ 0.392201, 0.181779, -0.069721, 1.151941, 0.392099, 0.201289, -0.076968, 1.151422, 0.391978,
+ 0.221678, -0.084518, 1.150861, 0.391833, 0.242752, -0.092017, 1.150156, 0.391618, 0.264474,
+ -0.100184, 1.149402, 0.391421, 0.286768, -0.108921, 1.148545, 0.391249, 0.310719, -0.116815,
+ 1.147388, 0.390773, 0.335638, -0.124785, 1.146042, 0.390168, 0.361240, -0.132630, 1.144529,
+ 0.389394, 0.387443, -0.140298, 1.142602, 0.388391, 0.414067, -0.147913, 1.140361, 0.387199,
+ 0.440904, -0.155362, 1.137612, 0.385742, 0.467771, -0.162574, 1.133659, 0.383926, 0.494907,
+ -0.169312, 1.129246, 0.381715, 0.522801, -0.174778, 1.124228, 0.378678, 0.550751, -0.179824,
+ 1.118697, 0.375158, 0.578018, -0.184284, 1.112019, 0.370851, 0.605291, -0.188215, 1.105151,
+ 0.365928, 0.632269, -0.190760, 1.097677, 0.360114, 0.659432, -0.192457, 1.090816, 0.353498,
+ 0.685839, -0.193458, 1.083286, 0.346094, 0.711876, -0.193502, 1.076245, 0.337754, 0.738184,
+ -0.192371, 1.069684, 0.328412, 0.763723, -0.190531, 1.063249, 0.318164, 0.789192, -0.187726,
+ 1.057265, 0.306900, 0.813744, -0.183783, 1.051177, 0.295021, 0.838408, -0.179328, 1.045902,
+ 0.282144, 0.862116, -0.173573, 1.040853, 0.268438, 0.885636, -0.167350, 1.036515, 0.254108,
+ 0.909342, -0.160229, 1.033269, 0.239082, 0.931962, -0.152529, 1.029627, 0.224024, 0.954671,
+ -0.144080, 1.027507, 0.208393, 0.975707, -0.135023, 1.024657, 0.192630, 0.996644, -0.125258,
+ 1.022998, 0.176741, 1.015817, -0.115089, 1.021234, 0.160926, 1.034301, -0.104317, 1.020025,
+ 0.145042, 1.051131, -0.093218, 1.018739, 0.129052, 1.066836, -0.081828, 1.017419, 0.112905,
+ 1.081027, -0.070132, 1.015714, 0.096578, 1.093225, -0.058382, 1.013465, 0.080077, 1.103691,
+ -0.046527, 1.010853, 0.063580, 1.112431, -0.034624, 1.007702, 0.047118, 1.120035, -0.022913,
+ 1.004551, 0.031018, 1.127336, -0.011284, 1.001924, 0.015283, 1.134510, 0.000170, 0.999937,
+ -0.000058, 0.000200, -0.000084, 1.177044, 0.421534, 0.000504, -0.000212, 1.177312, 0.421533,
+ 0.002016, -0.000850, 1.177730, 0.421533, 0.004535, -0.001912, 1.177722, 0.421533, 0.008063,
+ -0.003399, 1.177844, 0.421529, 0.012598, -0.005310, 1.177768, 0.421533, 0.018141, -0.007646,
+ 1.177730, 0.421531, 0.024692, -0.010407, 1.177663, 0.421530, 0.032252, -0.013592, 1.177681,
+ 0.421527, 0.040821, -0.017201, 1.177562, 0.421524, 0.050401, -0.021234, 1.177445, 0.421516,
+ 0.060988, -0.025688, 1.177461, 0.421509, 0.072590, -0.030565, 1.177364, 0.421498, 0.085200,
+ -0.035860, 1.177205, 0.421482, 0.098823, -0.041572, 1.177011, 0.421462, 0.113465, -0.047694,
+ 1.176794, 0.421436, 0.129094, -0.054122, 1.176504, 0.421396, 0.145652, -0.060530, 1.176203,
+ 0.421311, 0.163245, -0.067517, 1.175805, 0.421218, 0.181825, -0.074919, 1.175271, 0.421108,
+ 0.201360, -0.082700, 1.174717, 0.420974, 0.221773, -0.090727, 1.174021, 0.420795, 0.242908,
+ -0.098719, 1.173173, 0.420536, 0.264742, -0.107417, 1.172285, 0.420296, 0.287091, -0.116601,
+ 1.171326, 0.420065, 0.310723, -0.125265, 1.169907, 0.419582, 0.335685, -0.133876, 1.168352,
+ 0.418912, 0.361285, -0.142140, 1.166322, 0.418006, 0.387562, -0.150436, 1.164136, 0.416899,
+ 0.414175, -0.158388, 1.161162, 0.415513, 0.441021, -0.166258, 1.157608, 0.413836, 0.467698,
+ -0.173720, 1.152519, 0.411702, 0.494730, -0.180843, 1.147020, 0.409102, 0.522524, -0.186906,
+ 1.141256, 0.405789, 0.550055, -0.192004, 1.134114, 0.401759, 0.577512, -0.196588, 1.127086,
+ 0.397153, 0.604348, -0.200420, 1.119029, 0.391767, 0.630970, -0.203320, 1.110308, 0.385573,
+ 0.658023, -0.204883, 1.102643, 0.378245, 0.684422, -0.205716, 1.094573, 0.370191, 0.710405,
+ -0.205767, 1.086405, 0.361231, 0.736417, -0.204513, 1.078712, 0.351106, 0.761836, -0.202281,
+ 1.071619, 0.340096, 0.787140, -0.199395, 1.064873, 0.328139, 0.812197, -0.195185, 1.058313,
+ 0.315044, 0.836342, -0.190191, 1.052085, 0.300933, 0.860311, -0.184343, 1.046705, 0.286411,
+ 0.883597, -0.177415, 1.041072, 0.270897, 0.906852, -0.170003, 1.036797, 0.254825, 0.929991,
+ -0.161592, 1.033264, 0.238176, 0.952478, -0.152792, 1.030250, 0.221581, 0.974216, -0.143032,
+ 1.027331, 0.204378, 0.995372, -0.132922, 1.025135, 0.187470, 1.015330, -0.122009, 1.023250,
+ 0.170538, 1.034070, -0.110740, 1.022021, 0.153777, 1.051295, -0.099016, 1.020271, 0.136916,
+ 1.067460, -0.086920, 1.018948, 0.119880, 1.082022, -0.074729, 1.017336, 0.102565, 1.094378,
+ -0.062036, 1.014820, 0.084994, 1.104998, -0.049413, 1.011999, 0.067650, 1.113773, -0.036812,
+ 1.008711, 0.050148, 1.121263, -0.024274, 1.005141, 0.032976, 1.128420, -0.012038, 1.002196,
+ 0.016239, 1.135496, 0.000106, 1.000042, -0.000062, 0.000200, -0.000090, 1.203048, 0.451217,
+ 0.000504, -0.000227, 1.203226, 0.451215, 0.002016, -0.000909, 1.203450, 0.451215, 0.004535,
+ -0.002046, 1.203569, 0.451215, 0.008062, -0.003638, 1.203609, 0.451209, 0.012598, -0.005684,
+ 1.203580, 0.451214, 0.018141, -0.008185, 1.203515, 0.451212, 0.024694, -0.011141, 1.203618,
+ 0.451211, 0.032253, -0.014549, 1.203609, 0.451207, 0.040815, -0.018409, 1.203302, 0.451203,
+ 0.050401, -0.022727, 1.203454, 0.451195, 0.060990, -0.027495, 1.203480, 0.451188, 0.072591,
+ -0.032713, 1.203220, 0.451172, 0.085203, -0.038378, 1.203058, 0.451154, 0.098829, -0.044489,
+ 1.202838, 0.451130, 0.113466, -0.051031, 1.202530, 0.451098, 0.129084, -0.057808, 1.202270,
+ 0.451041, 0.145669, -0.064769, 1.201904, 0.450956, 0.163278, -0.072278, 1.201411, 0.450853,
+ 0.181880, -0.080224, 1.200825, 0.450721, 0.201436, -0.088537, 1.200164, 0.450566, 0.221865,
+ -0.097009, 1.199335, 0.450351, 0.243083, -0.105591, 1.198383, 0.450062, 0.265033, -0.114818,
+ 1.197380, 0.449769, 0.287456, -0.124372, 1.196137, 0.449438, 0.310758, -0.133892, 1.194554,
+ 0.448974, 0.335721, -0.143052, 1.192649, 0.448216, 0.361348, -0.151868, 1.190233, 0.447202,
+ 0.387573, -0.160644, 1.187211, 0.445926, 0.414159, -0.169028, 1.183452, 0.444313, 0.440950,
+ -0.177169, 1.178562, 0.442315, 0.467998, -0.185090, 1.173540, 0.439960, 0.494566, -0.192396,
+ 1.166344, 0.436989, 0.521730, -0.198915, 1.159283, 0.433439, 0.549405, -0.204240, 1.151503,
+ 0.428984, 0.576755, -0.208861, 1.143004, 0.423839, 0.603635, -0.212734, 1.134099, 0.418012,
+ 0.629979, -0.215712, 1.124555, 0.411445, 0.656597, -0.217385, 1.115293, 0.403628, 0.683317,
+ -0.218093, 1.106460, 0.394639, 0.708990, -0.217835, 1.097389, 0.385012, 0.734898, -0.216774,
+ 1.088940, 0.373999, 0.760342, -0.214120, 1.080385, 0.362128, 0.785517, -0.210821, 1.072959,
+ 0.349184, 0.809933, -0.206443, 1.065450, 0.335080, 0.834339, -0.200942, 1.058701, 0.320257,
+ 0.858793, -0.194938, 1.052711, 0.304133, 0.882300, -0.187615, 1.047044, 0.287771, 0.905560,
+ -0.179626, 1.042083, 0.270571, 0.927916, -0.170753, 1.037077, 0.252741, 0.950415, -0.161270,
+ 1.033200, 0.234656, 0.972920, -0.151239, 1.030418, 0.216652, 0.993893, -0.140358, 1.027479,
+ 0.198252, 1.014204, -0.128963, 1.024897, 0.180113, 1.033878, -0.117128, 1.023648, 0.162282,
+ 1.051754, -0.104678, 1.022230, 0.144366, 1.067924, -0.092000, 1.020453, 0.126455, 1.082643,
+ -0.078837, 1.018518, 0.108194, 1.095503, -0.065669, 1.016199, 0.089966, 1.106290, -0.052345,
+ 1.013113, 0.071530, 1.115219, -0.039024, 1.009636, 0.053158, 1.122587, -0.025789, 1.005801,
+ 0.034959, 1.129461, -0.012622, 1.002442, 0.017222, 1.136468, 0.000152, 0.999964, -0.000065,
+ 0.000200, -0.000096, 1.231156, 0.481574, 0.000504, -0.000243, 1.232187, 0.481572, 0.002016,
+ -0.000971, 1.231948, 0.481572, 0.004535, -0.002184, 1.231919, 0.481572, 0.008061, -0.003882,
+ 1.231453, 0.481566, 0.012597, -0.006066, 1.231800, 0.481572, 0.018142, -0.008736, 1.231756,
+ 0.481569, 0.024693, -0.011889, 1.232062, 0.481570, 0.032254, -0.015528, 1.231915, 0.481563,
+ 0.040822, -0.019650, 1.231863, 0.481559, 0.050402, -0.024255, 1.231737, 0.481550, 0.060992,
+ -0.029342, 1.231678, 0.481537, 0.072592, -0.034908, 1.231537, 0.481521, 0.085207, -0.040953,
+ 1.231336, 0.481499, 0.098834, -0.047469, 1.231071, 0.481469, 0.113474, -0.054441, 1.230757,
+ 0.481431, 0.129077, -0.061556, 1.230424, 0.481359, 0.145691, -0.069091, 1.230022, 0.481269,
+ 0.163321, -0.077151, 1.229461, 0.481156, 0.181936, -0.085636, 1.228718, 0.481011, 0.201516,
+ -0.094484, 1.228023, 0.480830, 0.221963, -0.103362, 1.227057, 0.480562, 0.243264, -0.112628,
+ 1.225997, 0.480247, 0.265291, -0.122366, 1.224744, 0.479891, 0.287824, -0.132256, 1.223255,
+ 0.479461, 0.310927, -0.142614, 1.221348, 0.478978, 0.335749, -0.152326, 1.218953, 0.478132,
+ 0.361361, -0.161747, 1.215806, 0.476971, 0.387480, -0.170879, 1.211853, 0.475477, 0.414231,
+ -0.179865, 1.207783, 0.473686, 0.441065, -0.188331, 1.202051, 0.471415, 0.467923, -0.196454,
+ 1.195463, 0.468647, 0.494526, -0.204048, 1.187542, 0.465459, 0.521318, -0.211020, 1.179235,
+ 0.461650, 0.548654, -0.216520, 1.170110, 0.456868, 0.575778, -0.221098, 1.160163, 0.451227,
+ 0.602610, -0.224923, 1.149751, 0.444866, 0.628891, -0.227895, 1.139169, 0.437577, 0.655635,
+ -0.230020, 1.129736, 0.429369, 0.682115, -0.230419, 1.119516, 0.419673, 0.707514, -0.229789,
+ 1.108277, 0.409143, 0.733169, -0.228520, 1.099159, 0.397296, 0.758342, -0.225793, 1.089839,
+ 0.384578, 0.783477, -0.222049, 1.081428, 0.370323, 0.808497, -0.217562, 1.073742, 0.355253,
+ 0.832790, -0.211697, 1.065850, 0.339282, 0.856677, -0.204989, 1.058834, 0.322181, 0.880662,
+ -0.197653, 1.053291, 0.304610, 0.903474, -0.188858, 1.046822, 0.286042, 0.926313, -0.179746,
+ 1.041663, 0.267224, 0.948458, -0.169542, 1.036532, 0.247978, 0.970873, -0.159005, 1.033008,
+ 0.228535, 0.992958, -0.147658, 1.029844, 0.208819, 1.013413, -0.135771, 1.026930, 0.189486,
+ 1.033483, -0.123256, 1.025545, 0.170422, 1.051872, -0.110401, 1.023935, 0.152075, 1.068396,
+ -0.096860, 1.022092, 0.133169, 1.083731, -0.083259, 1.020221, 0.114022, 1.096849, -0.069266,
+ 1.017663, 0.094772, 1.107864, -0.055203, 1.014524, 0.075432, 1.116600, -0.041097, 1.010514,
+ 0.055980, 1.123871, -0.027083, 1.006313, 0.036839, 1.130718, -0.013510, 1.002778, 0.018156,
+ 1.137649, 0.000154, 1.000033, -0.000028, 0.000200, -0.000103, 1.264025, 0.512670, 0.000504,
+ -0.000258, 1.262437, 0.512667, 0.002016, -0.001033, 1.262691, 0.512668, 0.004535, -0.002325,
+ 1.262834, 0.512667, 0.008063, -0.004133, 1.262783, 0.512659, 0.012598, -0.006458, 1.262803,
+ 0.512666, 0.018141, -0.009299, 1.262720, 0.512665, 0.024683, -0.012652, 1.262061, 0.512655,
+ 0.032257, -0.016532, 1.262858, 0.512656, 0.040826, -0.020919, 1.262709, 0.512649, 0.050403,
+ -0.025820, 1.262685, 0.512639, 0.060993, -0.031233, 1.262544, 0.512625, 0.072597, -0.037157,
+ 1.262435, 0.512607, 0.085211, -0.043587, 1.262209, 0.512581, 0.098842, -0.050520, 1.261907,
+ 0.512544, 0.113484, -0.057926, 1.261575, 0.512500, 0.129097, -0.065460, 1.261293, 0.512420,
+ 0.145727, -0.073543, 1.260736, 0.512316, 0.163375, -0.082134, 1.260117, 0.512190, 0.182011,
+ -0.091173, 1.259299, 0.512024, 0.201598, -0.100540, 1.258381, 0.511810, 0.222084, -0.109931,
+ 1.257293, 0.511505, 0.243446, -0.119838, 1.256050, 0.511151, 0.265574, -0.130090, 1.254607,
+ 0.510724, 0.288230, -0.140421, 1.252808, 0.510191, 0.311336, -0.151343, 1.250489, 0.509627,
+ 0.335719, -0.161689, 1.247279, 0.508688, 0.361314, -0.171748, 1.243467, 0.507393, 0.387541,
+ -0.181399, 1.239145, 0.505758, 0.414204, -0.190768, 1.233760, 0.503676, 0.441092, -0.199659,
+ 1.227433, 0.501129, 0.467789, -0.207934, 1.219247, 0.498078, 0.494454, -0.215747, 1.210441,
+ 0.494630, 0.520950, -0.222869, 1.200559, 0.490467, 0.547802, -0.228881, 1.189872, 0.485444,
+ 0.575563, -0.233760, 1.180081, 0.479268, 0.602426, -0.237566, 1.168544, 0.472272, 0.628772,
+ -0.240447, 1.156546, 0.464390, 0.654963, -0.242427, 1.145123, 0.455345, 0.681384, -0.242980,
+ 1.134322, 0.444885, 0.707173, -0.242150, 1.122665, 0.433338, 0.732477, -0.240435, 1.111733,
+ 0.420647, 0.757567, -0.237806, 1.101271, 0.406799, 0.782341, -0.233503, 1.091341, 0.391761,
+ 0.806690, -0.228346, 1.082042, 0.375576, 0.830804, -0.222386, 1.073504, 0.358545, 0.854940,
+ -0.215141, 1.065880, 0.340431, 0.878709, -0.207207, 1.058850, 0.321690, 0.901928, -0.198273,
+ 1.052588, 0.301930, 0.924845, -0.188476, 1.046521, 0.281513, 0.946932, -0.177996, 1.040966,
+ 0.261234, 0.969256, -0.166644, 1.036670, 0.240356, 0.991323, -0.154968, 1.032694, 0.219748,
+ 1.013013, -0.142425, 1.030061, 0.199103, 1.032845, -0.129456, 1.027254, 0.178936, 1.051887,
+ -0.115763, 1.025497, 0.159243, 1.069179, -0.101851, 1.023807, 0.139560, 1.084499, -0.087357,
+ 1.021441, 0.119607, 1.097921, -0.072796, 1.018780, 0.099501, 1.109281, -0.058037, 1.015566,
+ 0.079211, 1.118194, -0.043226, 1.011494, 0.058873, 1.125351, -0.028633, 1.007089, 0.038736,
+ 1.132002, -0.013996, 1.003014, 0.019063, 1.138951, 0.000132, 1.000036, -0.000007, 0.000200,
+ -0.000109, 1.296791, 0.544571, 0.000504, -0.000274, 1.296055, 0.544568, 0.002016, -0.001098,
+ 1.297239, 0.544568, 0.004535, -0.002470, 1.296600, 0.544568, 0.008062, -0.004390, 1.296368,
+ 0.544559, 0.012597, -0.006860, 1.296454, 0.544566, 0.018141, -0.009878, 1.296522, 0.544565,
+ 0.024693, -0.013444, 1.296536, 0.544560, 0.032256, -0.017559, 1.296638, 0.544557, 0.040824,
+ -0.022218, 1.296491, 0.544547, 0.050408, -0.027426, 1.296552, 0.544532, 0.060997, -0.033173,
+ 1.296283, 0.544518, 0.072600, -0.039463, 1.296113, 0.544496, 0.085220, -0.046292, 1.295894,
+ 0.544466, 0.098851, -0.053648, 1.295545, 0.544422, 0.113496, -0.061487, 1.295201, 0.544371,
+ 0.129112, -0.069467, 1.294754, 0.544273, 0.145765, -0.078092, 1.294209, 0.544160, 0.163431,
+ -0.087231, 1.293534, 0.544017, 0.182088, -0.096837, 1.292580, 0.543828, 0.201698, -0.106713,
+ 1.291586, 0.543585, 0.222231, -0.116699, 1.290325, 0.543238, 0.243653, -0.127208, 1.288888,
+ 0.542836, 0.265855, -0.137949, 1.287131, 0.542329, 0.288623, -0.148847, 1.284936, 0.541700,
+ 0.311830, -0.160204, 1.282109, 0.540997, 0.335728, -0.171324, 1.278036, 0.540045, 0.361403,
+ -0.181915, 1.273912, 0.538603, 0.387647, -0.192124, 1.268881, 0.536741, 0.414217, -0.201807,
+ 1.262363, 0.534432, 0.441090, -0.211093, 1.254755, 0.531623, 0.467823, -0.219678, 1.245456,
+ 0.528314, 0.494361, -0.227581, 1.234953, 0.524391, 0.521264, -0.235087, 1.224839, 0.519902,
+ 0.547881, -0.241508, 1.213175, 0.514574, 0.574965, -0.246315, 1.200505, 0.507837, 0.601847,
+ -0.250061, 1.187901, 0.500286, 0.628207, -0.252822, 1.174601, 0.491502, 0.654445, -0.254691,
+ 1.161944, 0.481726, 0.680175, -0.255318, 1.149305, 0.470727, 0.706168, -0.254257, 1.136708,
+ 0.458045, 0.731458, -0.252100, 1.124047, 0.444438, 0.756378, -0.249115, 1.112942, 0.429611,
+ 0.781311, -0.244899, 1.101800, 0.413501, 0.805755, -0.239225, 1.091662, 0.395889, 0.829867,
+ -0.232830, 1.082291, 0.377860, 0.853067, -0.225193, 1.072820, 0.358704, 0.877084, -0.216648,
+ 1.065415, 0.338413, 0.900123, -0.207390, 1.058403, 0.317596, 0.923370, -0.197095, 1.051412,
+ 0.296301, 0.946021, -0.186084, 1.045877, 0.274498, 0.967669, -0.174262, 1.040316, 0.252565,
+ 0.989761, -0.161814, 1.035489, 0.230312, 1.012163, -0.149076, 1.032540, 0.208746, 1.032547,
+ -0.135299, 1.029598, 0.187180, 1.052032, -0.121277, 1.027355, 0.166482, 1.069907, -0.106582,
+ 1.025622, 0.145939, 1.085563, -0.091589, 1.023244, 0.125362, 1.099447, -0.076263, 1.020661,
+ 0.104087, 1.110848, -0.060825, 1.017035, 0.083036, 1.119923, -0.045319, 1.012675, 0.061719,
+ 1.126805, -0.029852, 1.007668, 0.040583, 1.133282, -0.014846, 1.003335, 0.019969, 1.140128,
+ 0.000149, 1.000024, -0.000037, 0.000200, -0.000116, 1.334863, 0.577350, 0.000504, -0.000291,
+ 1.333350, 0.577348, 0.002015, -0.001164, 1.332853, 0.577347, 0.004535, -0.002618, 1.333295,
+ 0.577347, 0.008062, -0.004655, 1.333189, 0.577336, 0.012598, -0.007273, 1.333309, 0.577345,
+ 0.018141, -0.010472, 1.333274, 0.577342, 0.024694, -0.014253, 1.333231, 0.577339, 0.032254,
+ -0.018614, 1.333265, 0.577332, 0.040827, -0.023556, 1.333261, 0.577321, 0.050400, -0.029069,
+ 1.332893, 0.577309, 0.061000, -0.035166, 1.332998, 0.577288, 0.072608, -0.041833, 1.332901,
+ 0.577263, 0.085227, -0.049067, 1.332603, 0.577226, 0.098864, -0.056860, 1.332264, 0.577177,
+ 0.113507, -0.065114, 1.331825, 0.577109, 0.129146, -0.073610, 1.331311, 0.577005, 0.145808,
+ -0.082766, 1.330639, 0.576872, 0.163494, -0.092458, 1.329878, 0.576709, 0.182176, -0.102639,
+ 1.328889, 0.576501, 0.201804, -0.112983, 1.327710, 0.576207, 0.222394, -0.123650, 1.326256,
+ 0.575823, 0.243881, -0.134780, 1.324593, 0.575363, 0.266122, -0.145931, 1.322426, 0.574751,
+ 0.289043, -0.157500, 1.319837, 0.574033, 0.312330, -0.169208, 1.316301, 0.573181, 0.336120,
+ -0.181125, 1.312251, 0.572188, 0.361506, -0.192232, 1.307003, 0.570631, 0.387757, -0.202981,
+ 1.301068, 0.568558, 0.414365, -0.213160, 1.293695, 0.566027, 0.440986, -0.222617, 1.283958,
+ 0.562942, 0.467943, -0.231583, 1.274057, 0.559219, 0.494821, -0.239881, 1.262864, 0.554913,
+ 0.521486, -0.247336, 1.250633, 0.549953, 0.547884, -0.253921, 1.237448, 0.544251, 0.574582,
+ -0.259099, 1.223164, 0.537120, 0.601342, -0.262695, 1.208784, 0.528650, 0.627861, -0.265337,
+ 1.194424, 0.518978, 0.653745, -0.266872, 1.179361, 0.508525, 0.679348, -0.267403, 1.165010,
+ 0.496705, 0.705068, -0.266429, 1.151693, 0.482926, 0.730312, -0.263829, 1.137584, 0.468519,
+ 0.755576, -0.260491, 1.125328, 0.452213, 0.780371, -0.256166, 1.113759, 0.435127, 0.804632,
+ -0.250079, 1.101656, 0.416833, 0.828983, -0.243181, 1.091235, 0.397009, 0.852585, -0.235383,
+ 1.081475, 0.376647, 0.875237, -0.226031, 1.071806, 0.355506, 0.899152, -0.216343, 1.064453,
+ 0.333133, 0.922121, -0.205772, 1.057161, 0.311073, 0.944523, -0.193980, 1.050447, 0.287781,
+ 0.967313, -0.181920, 1.044531, 0.264350, 0.989042, -0.168822, 1.039312, 0.241128, 1.010881,
+ -0.155350, 1.035298, 0.218138, 1.032368, -0.141231, 1.032073, 0.195579, 1.052254, -0.126521,
+ 1.029395, 0.173399, 1.070207, -0.111243, 1.026938, 0.151866, 1.086528, -0.095617, 1.024957,
+ 0.130711, 1.100670, -0.079687, 1.021924, 0.108865, 1.112461, -0.063593, 1.018281, 0.086760,
+ 1.121588, -0.047313, 1.013747, 0.064575, 1.128522, -0.031385, 1.008433, 0.042499, 1.134759,
+ -0.015356, 1.003569, 0.020840, 1.141448, 0.000114, 0.999978, -0.000056, 0.000200, -0.000122,
+ 1.372763, 0.611086, 0.000503, -0.000308, 1.371456, 0.611084, 0.002016, -0.001232, 1.373440,
+ 0.611084, 0.004535, -0.002771, 1.373387, 0.611083, 0.008061, -0.004926, 1.372916, 0.611083,
+ 0.012601, -0.007700, 1.373956, 0.611084, 0.018142, -0.011084, 1.373419, 0.611078, 0.024695,
+ -0.015087, 1.373492, 0.611074, 0.032255, -0.019701, 1.373360, 0.611066, 0.040827, -0.024930,
+ 1.373327, 0.611055, 0.050408, -0.030769, 1.373222, 0.611037, 0.061004, -0.037217, 1.373079,
+ 0.611014, 0.072613, -0.044270, 1.372895, 0.610982, 0.085238, -0.051923, 1.372624, 0.610941,
+ 0.098878, -0.060161, 1.372252, 0.610883, 0.113522, -0.068785, 1.371785, 0.610798, 0.129176,
+ -0.077863, 1.371103, 0.610683, 0.145876, -0.087593, 1.370541, 0.610537, 0.163570, -0.097847,
+ 1.369496, 0.610349, 0.182283, -0.108592, 1.368477, 0.610109, 0.201930, -0.119420, 1.366980,
+ 0.609763, 0.222570, -0.130789, 1.365375, 0.609343, 0.244123, -0.142514, 1.363456, 0.608815,
+ 0.266437, -0.154232, 1.360916, 0.608114, 0.289467, -0.166370, 1.357909, 0.607291, 0.312861,
+ -0.178505, 1.353588, 0.606272, 0.336736, -0.190980, 1.349211, 0.605153, 0.361740, -0.202859,
+ 1.343319, 0.603548, 0.387878, -0.213997, 1.335908, 0.601268, 0.414357, -0.224584, 1.326676,
+ 0.598499, 0.441442, -0.234664, 1.317331, 0.595066, 0.468409, -0.243875, 1.305818, 0.590996,
+ 0.494999, -0.252121, 1.291863, 0.586293, 0.521730, -0.259714, 1.278212, 0.580840, 0.547894,
+ -0.266242, 1.262656, 0.574494, 0.573865, -0.271578, 1.246364, 0.567007, 0.601124, -0.275503,
+ 1.231274, 0.557771, 0.627606, -0.277954, 1.215252, 0.547255, 0.654004, -0.279404, 1.199977,
+ 0.535766, 0.679554, -0.279632, 1.183995, 0.522792, 0.704280, -0.278457, 1.167428, 0.508488,
+ 0.729830, -0.275706, 1.152760, 0.492425, 0.754376, -0.271640, 1.137942, 0.475285, 0.779209,
+ -0.266911, 1.125222, 0.456679, 0.803562, -0.260838, 1.112179, 0.437267, 0.827985, -0.253353,
+ 1.101439, 0.416227, 0.851737, -0.245027, 1.089890, 0.394728, 0.874850, -0.235719, 1.080018,
+ 0.372244, 0.897680, -0.225051, 1.070807, 0.348846, 0.921351, -0.214051, 1.063180, 0.324961,
+ 0.943818, -0.202039, 1.056148, 0.300836, 0.966368, -0.189134, 1.049277, 0.276333, 0.987426,
+ -0.175613, 1.042176, 0.251862, 1.010162, -0.161473, 1.038567, 0.227217, 1.031224, -0.146866,
+ 1.034102, 0.203582, 1.052317, -0.131644, 1.031600, 0.180629, 1.070879, -0.115909, 1.028913,
+ 0.158165, 1.087407, -0.099638, 1.026193, 0.135905, 1.102159, -0.083091, 1.023567, 0.113394,
+ 1.114006, -0.066178, 1.019567, 0.090325, 1.123374, -0.049430, 1.014856, 0.067302, 1.130310,
+ -0.032557, 1.009141, 0.044264, 1.136334, -0.016157, 1.003984, 0.021807, 1.142961, 0.000172,
+ 0.999951, -0.000077, 0.000200, -0.000129, 1.416584, 0.645866, 0.000504, -0.000326, 1.417762,
+ 0.645865, 0.002016, -0.001302, 1.417825, 0.645866, 0.004535, -0.002929, 1.417142, 0.645865,
+ 0.008062, -0.005207, 1.416968, 0.645864, 0.012598, -0.008136, 1.417109, 0.645862, 0.018141,
+ -0.011715, 1.417001, 0.645859, 0.024690, -0.015941, 1.416878, 0.645853, 0.032257, -0.020823,
+ 1.417134, 0.645843, 0.040827, -0.026347, 1.416983, 0.645829, 0.050411, -0.032518, 1.416949,
+ 0.645808, 0.061007, -0.039330, 1.416694, 0.645781, 0.072621, -0.046783, 1.416599, 0.645746,
+ 0.085249, -0.054865, 1.416241, 0.645695, 0.098897, -0.063563, 1.415832, 0.645630, 0.113546,
+ -0.072607, 1.415264, 0.645529, 0.129220, -0.082257, 1.414482, 0.645396, 0.145888, -0.092515,
+ 1.413626, 0.645268, 0.163659, -0.103393, 1.412710, 0.645018, 0.182385, -0.114684, 1.411418,
+ 0.644739, 0.202078, -0.126098, 1.409822, 0.644348, 0.222772, -0.138145, 1.407948, 0.643872,
+ 0.244370, -0.150405, 1.405678, 0.643255, 0.266787, -0.162798, 1.402763, 0.642463, 0.289844,
+ -0.175434, 1.398863, 0.641504, 0.313540, -0.188158, 1.394695, 0.640346, 0.337489, -0.201014,
+ 1.389376, 0.639042, 0.362008, -0.213719, 1.382439, 0.637412, 0.387990, -0.225248, 1.373281,
+ 0.634930, 0.414728, -0.236348, 1.363729, 0.631861, 0.441635, -0.246701, 1.352304, 0.628155,
+ 0.468588, -0.256167, 1.339162, 0.623625, 0.495337, -0.264662, 1.323811, 0.618458, 0.521886,
+ -0.272207, 1.307630, 0.612373, 0.548355, -0.278890, 1.291265, 0.605263, 0.574535, -0.284442,
+ 1.273752, 0.597048, 0.600870, -0.288389, 1.256171, 0.587401, 0.627715, -0.290816, 1.238447,
+ 0.576001, 0.653830, -0.291886, 1.221036, 0.563198, 0.679175, -0.291629, 1.202283, 0.549249,
+ 0.704539, -0.290489, 1.185866, 0.533881, 0.729126, -0.287529, 1.168822, 0.516966, 0.754297,
+ -0.283184, 1.152934, 0.498501, 0.778678, -0.277732, 1.137821, 0.478728, 0.802473, -0.271203,
+ 1.123387, 0.457814, 0.826596, -0.263494, 1.110573, 0.435865, 0.850835, -0.254572, 1.099099,
+ 0.412597, 0.874203, -0.244815, 1.088403, 0.388995, 0.897271, -0.233993, 1.078085, 0.364487,
+ 0.919667, -0.221934, 1.068543, 0.339344, 0.943001, -0.209714, 1.061081, 0.313770, 0.965688,
+ -0.196367, 1.054023, 0.287928, 0.987598, -0.182263, 1.047247, 0.262157, 1.009280, -0.167775,
+ 1.041376, 0.236855, 1.031762, -0.152530, 1.037647, 0.211847, 1.051965, -0.136809, 1.033396,
+ 0.187546, 1.071699, -0.120418, 1.031021, 0.164186, 1.088881, -0.103618, 1.028403, 0.141184,
+ 1.103482, -0.086271, 1.024987, 0.117665, 1.115646, -0.068973, 1.020884, 0.093896, 1.125258,
+ -0.051285, 1.015966, 0.069978, 1.132045, -0.033998, 1.009990, 0.046126, 1.138004, -0.016696,
+ 1.004270, 0.022635, 1.144463, 0.000089, 0.999987, -0.000016, 0.000200, -0.000136, 1.463614,
+ 0.681786, 0.000504, -0.000344, 1.465345, 0.681785, 0.002015, -0.001374, 1.464172, 0.681783,
+ 0.004535, -0.003092, 1.464846, 0.681784, 0.008062, -0.005496, 1.464783, 0.681784, 0.012598,
+ -0.008588, 1.464883, 0.681781, 0.018141, -0.012366, 1.464740, 0.681777, 0.024692, -0.016829,
+ 1.464665, 0.681770, 0.032258, -0.021980, 1.464720, 0.681760, 0.040829, -0.027811, 1.464625,
+ 0.681742, 0.050415, -0.034324, 1.464571, 0.681720, 0.061013, -0.041513, 1.464346, 0.681688,
+ 0.072628, -0.049375, 1.464131, 0.681644, 0.085264, -0.057903, 1.463847, 0.681588, 0.098918,
+ -0.067067, 1.463369, 0.681509, 0.113568, -0.076570, 1.462549, 0.681389, 0.129265, -0.086782,
+ 1.461703, 0.681239, 0.145997, -0.097637, 1.460840, 0.681047, 0.163751, -0.109101, 1.459737,
+ 0.680806, 0.182505, -0.120922, 1.458231, 0.680480, 0.202241, -0.133007, 1.456393, 0.680042,
+ 0.222987, -0.145693, 1.454258, 0.679503, 0.244638, -0.158488, 1.451543, 0.678792, 0.267132,
+ -0.171585, 1.448115, 0.677907, 0.290365, -0.184746, 1.443992, 0.676796, 0.314178, -0.198101,
+ 1.439271, 0.675498, 0.338289, -0.211370, 1.432830, 0.673922, 0.362543, -0.224489, 1.424163,
+ 0.672151, 0.388470, -0.236914, 1.415160, 0.669601, 0.415105, -0.248342, 1.403811, 0.666255,
+ 0.441925, -0.258957, 1.390149, 0.662166, 0.468668, -0.268556, 1.374104, 0.657229, 0.495720,
+ -0.277359, 1.358102, 0.651347, 0.522574, -0.285078, 1.340754, 0.644598, 0.548981, -0.291718,
+ 1.322033, 0.636820, 0.574946, -0.297087, 1.302148, 0.627812, 0.600744, -0.301079, 1.282130,
+ 0.617485, 0.627565, -0.303566, 1.263339, 0.605047, 0.653598, -0.304330, 1.242712, 0.591167,
+ 0.679239, -0.303820, 1.223212, 0.576025, 0.704043, -0.302064, 1.203763, 0.559649, 0.728796,
+ -0.299095, 1.185434, 0.541271, 0.753581, -0.294392, 1.167630, 0.521800, 0.778577, -0.288603,
+ 1.151930, 0.500628, 0.802550, -0.281604, 1.136072, 0.478434, 0.825803, -0.273472, 1.121673,
+ 0.455384, 0.849768, -0.264011, 1.108491, 0.430811, 0.873250, -0.253653, 1.096550, 0.405524,
+ 0.896725, -0.242642, 1.085905, 0.380038, 0.919158, -0.230191, 1.075091, 0.353482, 0.942236,
+ -0.217145, 1.066848, 0.326605, 0.965031, -0.203555, 1.059310, 0.299842, 0.987048, -0.188777,
+ 1.051749, 0.272859, 1.008718, -0.173613, 1.044999, 0.246040, 1.031097, -0.157972, 1.040066,
+ 0.219826, 1.052493, -0.141589, 1.035951, 0.194278, 1.071773, -0.124814, 1.032520, 0.169830,
+ 1.089646, -0.107321, 1.029803, 0.146135, 1.104932, -0.089726, 1.026612, 0.122127, 1.117687,
+ -0.071433, 1.022391, 0.097461, 1.127188, -0.053395, 1.017113, 0.072556, 1.134010, -0.035151,
+ 1.010934, 0.047749, 1.139746, -0.017427, 1.004633, 0.023530, 1.146205, 0.000151, 1.000020,
+ -0.000106, 0.000200, -0.000144, 1.517643, 0.718949, 0.000504, -0.000362, 1.516387, 0.718947,
+ 0.002016, -0.001449, 1.516742, 0.718946, 0.004536, -0.003261, 1.517196, 0.718946, 0.008063,
+ -0.005796, 1.516806, 0.718945, 0.012598, -0.009057, 1.516986, 0.718943, 0.018140, -0.013039,
+ 1.516603, 0.718937, 0.024694, -0.017747, 1.516739, 0.718929, 0.032260, -0.023178, 1.516994,
+ 0.718917, 0.040831, -0.029325, 1.516649, 0.718896, 0.050419, -0.036192, 1.516594, 0.718870,
+ 0.061019, -0.043770, 1.516327, 0.718833, 0.072638, -0.052056, 1.516054, 0.718782, 0.085274,
+ -0.061039, 1.515628, 0.718714, 0.098938, -0.070676, 1.515199, 0.718623, 0.113607, -0.080679,
+ 1.514222, 0.718483, 0.129329, -0.091485, 1.513354, 0.718316, 0.146077, -0.102931, 1.512301,
+ 0.718096, 0.163856, -0.114986, 1.510977, 0.717818, 0.182640, -0.127305, 1.509225, 0.717432,
+ 0.202432, -0.140147, 1.507152, 0.716939, 0.223229, -0.153468, 1.504780, 0.716331, 0.244943,
+ -0.166875, 1.501612, 0.715527, 0.267559, -0.180658, 1.497898, 0.714523, 0.290926, -0.194405,
+ 1.493208, 0.713266, 0.314863, -0.208302, 1.487388, 0.711758, 0.339053, -0.222020, 1.479677,
+ 0.709982, 0.363627, -0.235683, 1.470950, 0.707958, 0.388887, -0.248723, 1.459907, 0.705346,
+ 0.415474, -0.260563, 1.446579, 0.701644, 0.442065, -0.271352, 1.429962, 0.697134, 0.469418,
+ -0.281541, 1.414343, 0.691665, 0.496419, -0.290429, 1.395681, 0.685227, 0.523071, -0.298032,
+ 1.375347, 0.677815, 0.549641, -0.304679, 1.354816, 0.669063, 0.575489, -0.309902, 1.332505,
+ 0.659071, 0.601108, -0.313771, 1.309752, 0.647799, 0.627199, -0.316225, 1.288381, 0.634856,
+ 0.653243, -0.316679, 1.265785, 0.619627, 0.678960, -0.315816, 1.244333, 0.603244, 0.704055,
+ -0.313776, 1.223315, 0.585191, 0.728713, -0.310417, 1.203142, 0.565969, 0.753301, -0.305786,
+ 1.184323, 0.545347, 0.777890, -0.299262, 1.166070, 0.522753, 0.802354, -0.291830, 1.149599,
+ 0.499017, 0.826005, -0.283281, 1.133655, 0.474335, 0.848920, -0.273512, 1.118132, 0.449019,
+ 0.872765, -0.262525, 1.105606, 0.422329, 0.895950, -0.250769, 1.093539, 0.395057, 0.918816,
+ -0.238257, 1.082388, 0.367709, 0.941089, -0.224381, 1.072484, 0.339350, 0.964514, -0.210289,
+ 1.064054, 0.311239, 0.987128, -0.195488, 1.056645, 0.283272, 1.009064, -0.179491, 1.049549,
+ 0.255163, 1.030163, -0.163172, 1.042741, 0.227757, 1.052502, -0.146457, 1.038270, 0.200970,
+ 1.072971, -0.129054, 1.035014, 0.175767, 1.091223, -0.111285, 1.032231, 0.151118, 1.106518,
+ -0.092617, 1.028211, 0.126196, 1.119235, -0.074168, 1.023686, 0.100828, 1.129311, -0.055212,
+ 1.018311, 0.075240, 1.135983, -0.036571, 1.011485, 0.049558, 1.141648, -0.017954, 1.004952,
+ 0.024273, 1.147938, 0.000125, 1.000009, -0.000048, 0.000199, -0.000151, 1.566887, 0.757466,
+ 0.000504, -0.000382, 1.574111, 0.757466, 0.002016, -0.001527, 1.573735, 0.757466, 0.004535,
+ -0.003435, 1.573737, 0.757466, 0.008062, -0.006107, 1.573782, 0.757464, 0.012599, -0.009542,
+ 1.573796, 0.757460, 0.018142, -0.013739, 1.573710, 0.757455, 0.024694, -0.018697, 1.573562,
+ 0.757446, 0.032259, -0.024418, 1.573667, 0.757429, 0.040834, -0.030895, 1.573555, 0.757407,
+ 0.050422, -0.038127, 1.573383, 0.757376, 0.061025, -0.046108, 1.573086, 0.757332, 0.072650,
+ -0.054835, 1.572833, 0.757274, 0.085296, -0.064294, 1.572395, 0.757195, 0.098962, -0.074376,
+ 1.571729, 0.757087, 0.113649, -0.084955, 1.570571, 0.756925, 0.129389, -0.096334, 1.569582,
+ 0.756729, 0.146167, -0.108406, 1.568444, 0.756481, 0.163973, -0.121056, 1.566905, 0.756158,
+ 0.182798, -0.133970, 1.564939, 0.755715, 0.202650, -0.147522, 1.562666, 0.755167, 0.223502,
+ -0.161466, 1.559877, 0.754465, 0.245269, -0.175539, 1.556008, 0.753552, 0.268010, -0.189957,
+ 1.552013, 0.752420, 0.291474, -0.204361, 1.546509, 0.751008, 0.315527, -0.218714, 1.539575,
+ 0.749266, 0.339954, -0.233029, 1.530968, 0.747232, 0.364649, -0.247149, 1.520994, 0.744906,
+ 0.389520, -0.260672, 1.507748, 0.742123, 0.415717, -0.272873, 1.491777, 0.738187, 0.442862,
+ -0.284317, 1.475658, 0.733189, 0.469939, -0.294552, 1.456572, 0.727165, 0.496916, -0.303517,
+ 1.435237, 0.720043, 0.523480, -0.311061, 1.412192, 0.711640, 0.550092, -0.317596, 1.389033,
+ 0.702174, 0.576384, -0.322921, 1.365086, 0.691225, 0.602280, -0.326806, 1.341317, 0.678841,
+ 0.627676, -0.329057, 1.316518, 0.664815, 0.653458, -0.329372, 1.291877, 0.648548, 0.679227,
+ -0.328067, 1.268126, 0.630676, 0.704476, -0.325585, 1.244424, 0.611585, 0.729232, -0.321775,
+ 1.223010, 0.590803, 0.753405, -0.316713, 1.201297, 0.568653, 0.777274, -0.309858, 1.181071,
+ 0.544763, 0.801882, -0.301866, 1.162826, 0.519747, 0.826030, -0.292861, 1.145704, 0.493531,
+ 0.849359, -0.282794, 1.129629, 0.466900, 0.871837, -0.271197, 1.114155, 0.439230, 0.895896,
+ -0.258954, 1.102334, 0.410570, 0.918951, -0.245878, 1.090163, 0.381314, 0.941148, -0.231897,
+ 1.078738, 0.352268, 0.963464, -0.216743, 1.068862, 0.322688, 0.986628, -0.201486, 1.061077,
+ 0.293523, 1.009289, -0.185521, 1.053561, 0.264125, 1.030659, -0.168429, 1.046627, 0.235706,
+ 1.052382, -0.151210, 1.040953, 0.208022, 1.073476, -0.133289, 1.036534, 0.181245, 1.092237,
+ -0.114768, 1.033580, 0.155661, 1.108200, -0.095917, 1.029997, 0.130223, 1.121435, -0.076492,
+ 1.025374, 0.104098, 1.131382, -0.057204, 1.019485, 0.077776, 1.137994, -0.037747, 1.012188,
+ 0.051250, 1.143441, -0.018673, 1.005309, 0.025245, 1.149714, 0.000216, 1.000004, -0.000120,
+ 0.000200, -0.000159, 1.633988, 0.797469, 0.000504, -0.000402, 1.636076, 0.797469, 0.002016,
+ -0.001607, 1.635679, 0.797467, 0.004535, -0.003617, 1.636040, 0.797468, 0.008063, -0.006430,
+ 1.636159, 0.797467, 0.012599, -0.010046, 1.636128, 0.797462, 0.018141, -0.014464, 1.635730,
+ 0.797457, 0.024696, -0.019685, 1.635836, 0.797445, 0.032259, -0.025705, 1.635719, 0.797426,
+ 0.040835, -0.032523, 1.635610, 0.797401, 0.050425, -0.040135, 1.635460, 0.797363, 0.061033,
+ -0.048536, 1.635182, 0.797313, 0.072661, -0.057718, 1.634817, 0.797243, 0.085315, -0.067666,
+ 1.634314, 0.797150, 0.098985, -0.078179, 1.633350, 0.797016, 0.113699, -0.089383, 1.632253,
+ 0.796839, 0.129456, -0.101364, 1.631025, 0.796623, 0.146275, -0.114081, 1.629867, 0.796331,
+ 0.164108, -0.127318, 1.628043, 0.795956, 0.182983, -0.140901, 1.625813, 0.795458, 0.202891,
+ -0.155174, 1.623149, 0.794834, 0.223787, -0.169654, 1.619686, 0.794015, 0.245678, -0.184540,
+ 1.615694, 0.793013, 0.268495, -0.199543, 1.610812, 0.791727, 0.292093, -0.214639, 1.604629,
+ 0.790107, 0.316184, -0.229499, 1.596061, 0.788154, 0.340986, -0.244407, 1.587195, 0.785797,
+ 0.365808, -0.258907, 1.575031, 0.783093, 0.390528, -0.272746, 1.559448, 0.779970, 0.416510,
+ -0.285845, 1.543294, 0.775852, 0.443443, -0.297404, 1.523476, 0.770323, 0.470442, -0.307757,
+ 1.501515, 0.763721, 0.497499, -0.316846, 1.477841, 0.755889, 0.524316, -0.324561, 1.452427,
+ 0.746662, 0.551212, -0.331060, 1.427421, 0.736004, 0.577323, -0.335956, 1.400369, 0.723810,
+ 0.602976, -0.339501, 1.373093, 0.710184, 0.628357, -0.341577, 1.345853, 0.695017, 0.653642,
+ -0.342031, 1.319040, 0.677972, 0.679440, -0.340342, 1.292490, 0.658877, 0.704744, -0.337356,
+ 1.267182, 0.638085, 0.729692, -0.333042, 1.243280, 0.615615, 0.753920, -0.327504, 1.219751,
+ 0.592054, 0.777695, -0.320537, 1.197796, 0.566967, 0.801426, -0.311880, 1.176872, 0.540643,
+ 0.825649, -0.302211, 1.158160, 0.512906, 0.849282, -0.291665, 1.141257, 0.484587, 0.872341,
+ -0.280050, 1.125469, 0.455556, 0.895110, -0.266978, 1.110222, 0.425652, 0.918841, -0.253326,
+ 1.097419, 0.395015, 0.941209, -0.238899, 1.086101, 0.364948, 0.963142, -0.223523, 1.075023,
+ 0.334151, 0.985996, -0.207346, 1.065628, 0.303708, 1.008718, -0.190889, 1.057256, 0.273008,
+ 1.030554, -0.173517, 1.049720, 0.243221, 1.053085, -0.155645, 1.043837, 0.214426, 1.074267,
+ -0.137472, 1.039312, 0.187036, 1.093591, -0.118385, 1.035457, 0.160512, 1.109850, -0.098883,
+ 1.031630, 0.134384, 1.123516, -0.079050, 1.026762, 0.107424, 1.133578, -0.058977, 1.020640,
+ 0.080317, 1.140289, -0.039013, 1.013096, 0.052944, 1.145610, -0.019228, 1.005694, 0.025989,
+ 1.151704, 0.000105, 0.999981, -0.000019, 0.000200, -0.000168, 1.704841, 0.839096, 0.000504,
+ -0.000423, 1.704242, 0.839097, 0.002016, -0.001691, 1.703821, 0.839091, 0.004534, -0.003805,
+ 1.703804, 0.839094, 0.008063, -0.006765, 1.704224, 0.839092, 0.012598, -0.010570, 1.704013,
+ 0.839087, 0.018142, -0.015219, 1.703889, 0.839079, 0.024697, -0.020712, 1.704023, 0.839066,
+ 0.032261, -0.027046, 1.703836, 0.839045, 0.040837, -0.034218, 1.703608, 0.839014, 0.050429,
+ -0.042224, 1.703414, 0.838972, 0.061041, -0.051061, 1.703148, 0.838912, 0.072676, -0.060717,
+ 1.702744, 0.838831, 0.085340, -0.071175, 1.702223, 0.838724, 0.099023, -0.082182, 1.700984,
+ 0.838567, 0.113759, -0.094007, 1.699764, 0.838367, 0.129546, -0.106621, 1.698462, 0.838112,
+ 0.146382, -0.119956, 1.696938, 0.837782, 0.164260, -0.133760, 1.694868, 0.837346, 0.183188,
+ -0.148108, 1.692262, 0.836780, 0.203158, -0.163075, 1.689251, 0.836073, 0.224147, -0.178255,
+ 1.685408, 0.835148, 0.246147, -0.193900, 1.680946, 0.833992, 0.269072, -0.209553, 1.675277,
+ 0.832546, 0.292718, -0.225226, 1.667626, 0.830727, 0.317159, -0.240836, 1.658952, 0.828510,
+ 0.341979, -0.256103, 1.647624, 0.825843, 0.366844, -0.270887, 1.633014, 0.822760, 0.392043,
+ -0.285324, 1.617191, 0.819159, 0.417356, -0.298817, 1.597501, 0.814788, 0.444093, -0.310711,
+ 1.575184, 0.808751, 0.471379, -0.321410, 1.551590, 0.801294, 0.498267, -0.330421, 1.524134,
+ 0.792711, 0.525401, -0.338331, 1.496672, 0.782480, 0.551846, -0.344430, 1.467062, 0.770659,
+ 0.578009, -0.349047, 1.436943, 0.757348, 0.604054, -0.352490, 1.407611, 0.742541, 0.629387,
+ -0.354158, 1.377441, 0.726071, 0.654435, -0.354422, 1.347651, 0.707524, 0.679845, -0.352663,
+ 1.318769, 0.687067, 0.704892, -0.348994, 1.290600, 0.664637, 0.729763, -0.344105, 1.263997,
+ 0.640663, 0.754345, -0.338129, 1.239273, 0.615484, 0.778629, -0.330905, 1.215858, 0.589210,
+ 0.801939, -0.322113, 1.192318, 0.561550, 0.825723, -0.311673, 1.171380, 0.532175, 0.849387,
+ -0.300410, 1.152991, 0.502055, 0.872792, -0.288328, 1.136139, 0.471308, 0.895083, -0.275087,
+ 1.119534, 0.440427, 0.918335, -0.260700, 1.105542, 0.409260, 0.941577, -0.245717, 1.093070,
+ 0.377142, 0.963992, -0.230079, 1.081207, 0.345289, 0.986510, -0.213523, 1.071488, 0.313508,
+ 1.008806, -0.196157, 1.062011, 0.281962, 1.030724, -0.178467, 1.053240, 0.251177, 1.053782,
+ -0.160291, 1.047057, 0.220986, 1.075451, -0.141308, 1.041842, 0.192256, 1.094947, -0.121975,
+ 1.037704, 0.165023, 1.111783, -0.101744, 1.033300, 0.138228, 1.125525, -0.081476, 1.028234,
+ 0.110679, 1.135873, -0.060770, 1.021695, 0.082672, 1.142478, -0.040207, 1.013838, 0.054506,
+ 1.147889, -0.019908, 1.006166, 0.026938, 1.153852, 0.000204, 0.999983, -0.000123, 0.000199,
+ -0.000176, 1.771601, 0.882501, 0.000504, -0.000445, 1.779195, 0.882504, 0.002016, -0.001779,
+ 1.779635, 0.882498, 0.004536, -0.004003, 1.779586, 0.882499, 0.008062, -0.007115, 1.778613,
+ 0.882496, 0.012598, -0.011116, 1.778678, 0.882492, 0.018142, -0.016005, 1.778531, 0.882481,
+ 0.024696, -0.021782, 1.778556, 0.882466, 0.032262, -0.028444, 1.778507, 0.882442, 0.040842,
+ -0.035987, 1.778385, 0.882408, 0.050436, -0.044404, 1.778034, 0.882364, 0.061053, -0.053695,
+ 1.777761, 0.882287, 0.072692, -0.063842, 1.777256, 0.882190, 0.085364, -0.074821, 1.776518,
+ 0.882067, 0.099064, -0.086368, 1.775080, 0.881884, 0.113828, -0.098805, 1.773836, 0.881657,
+ 0.129649, -0.112090, 1.772370, 0.881361, 0.146518, -0.126067, 1.770594, 0.880982, 0.164440,
+ -0.140493, 1.768089, 0.880484, 0.183437, -0.155646, 1.765301, 0.879843, 0.203468, -0.171266,
+ 1.761698, 0.879035, 0.224562, -0.187231, 1.757518, 0.877982, 0.246665, -0.203540, 1.752318,
+ 0.876667, 0.269652, -0.219916, 1.745356, 0.875028, 0.293531, -0.236255, 1.737186, 0.872977,
+ 0.318048, -0.252410, 1.726709, 0.870448, 0.342963, -0.268192, 1.713109, 0.867400, 0.368336,
+ -0.283587, 1.698087, 0.863882, 0.393512, -0.298186, 1.678638, 0.859724, 0.418602, -0.311882,
+ 1.655604, 0.854835, 0.445080, -0.324500, 1.632250, 0.848353, 0.472289, -0.335295, 1.605069,
+ 0.840218, 0.499128, -0.344256, 1.573846, 0.830556, 0.525834, -0.351716, 1.541120, 0.819269,
+ 0.553177, -0.358241, 1.511385, 0.806222, 0.579480, -0.362640, 1.477866, 0.791647, 0.605205,
+ -0.365513, 1.444218, 0.775398, 0.630617, -0.366822, 1.410954, 0.757144, 0.655730, -0.366785,
+ 1.379010, 0.737323, 0.680529, -0.364904, 1.347280, 0.715601, 0.705800, -0.360990, 1.316416,
+ 0.691547, 0.730550, -0.355397, 1.286344, 0.666141, 0.754970, -0.348664, 1.258954, 0.638929,
+ 0.779042, -0.340774, 1.232965, 0.611015, 0.802839, -0.331767, 1.209775, 0.581877, 0.825793,
+ -0.321054, 1.185813, 0.551509, 0.849512, -0.309016, 1.165080, 0.519698, 0.873120, -0.296369,
+ 1.147091, 0.487506, 0.895942, -0.282704, 1.129658, 0.455320, 0.917996, -0.268007, 1.113463,
+ 0.422605, 0.941281, -0.252329, 1.100040, 0.389347, 0.964584, -0.236203, 1.087973, 0.356430,
+ 0.986371, -0.219209, 1.075983, 0.323089, 1.009522, -0.201588, 1.066940, 0.290806, 1.031976,
+ -0.183296, 1.057999, 0.258682, 1.053461, -0.164509, 1.049542, 0.227722, 1.076121, -0.145165,
+ 1.043718, 0.197439, 1.096597, -0.125199, 1.039607, 0.169578, 1.113908, -0.104921, 1.035528,
+ 0.142222, 1.127939, -0.083623, 1.029807, 0.113802, 1.138391, -0.062589, 1.023312, 0.085164,
+ 1.145110, -0.041376, 1.014806, 0.056186, 1.150141, -0.020433, 1.006501, 0.027654, 1.156069,
+ 0.000097, 0.999949, -0.000046, 0.000200, -0.000185, 1.858268, 0.927857, 0.000504, -0.000468,
+ 1.861583, 0.927859, 0.002016, -0.001870, 1.860659, 0.927855, 0.004535, -0.004208, 1.860963,
+ 0.927867, 0.008063, -0.007480, 1.860766, 0.927855, 0.012594, -0.011683, 1.859996, 0.927851,
+ 0.018142, -0.016828, 1.860739, 0.927839, 0.024698, -0.022901, 1.860763, 0.927818, 0.032263,
+ -0.029903, 1.860501, 0.927791, 0.040846, -0.037834, 1.860431, 0.927751, 0.050440, -0.046680,
+ 1.859827, 0.927690, 0.061066, -0.056446, 1.859624, 0.927610, 0.072713, -0.067109, 1.859039,
+ 0.927505, 0.085393, -0.078613, 1.858144, 0.927357, 0.099120, -0.090747, 1.856618, 0.927145,
+ 0.113910, -0.103850, 1.855221, 0.926884, 0.129755, -0.117777, 1.853470, 0.926546, 0.146669,
+ -0.132441, 1.851413, 0.926104, 0.164648, -0.147565, 1.848498, 0.925530, 0.183708, -0.163470,
+ 1.845281, 0.924802, 0.203832, -0.179763, 1.841273, 0.923871, 0.225029, -0.196564, 1.836481,
+ 0.922691, 0.247221, -0.213537, 1.830273, 0.921198, 0.270343, -0.230662, 1.822374, 0.919320,
+ 0.294399, -0.247740, 1.812975, 0.917008, 0.319040, -0.264448, 1.800693, 0.914141, 0.344269,
+ -0.280831, 1.785923, 0.910707, 0.369625, -0.296478, 1.767203, 0.906585, 0.394925, -0.311287,
+ 1.744434, 0.901918, 0.420583, -0.325578, 1.720938, 0.896240, 0.446200, -0.338384, 1.693005,
+ 0.889335, 0.472969, -0.349187, 1.660901, 0.880394, 0.500490, -0.358687, 1.628806, 0.869705,
+ 0.527312, -0.366042, 1.593001, 0.857145, 0.554207, -0.372045, 1.557046, 0.842943, 0.580620,
+ -0.376134, 1.520192, 0.826837, 0.606480, -0.378636, 1.482947, 0.808891, 0.631815, -0.379414,
+ 1.445954, 0.789119, 0.657021, -0.378972, 1.410833, 0.767564, 0.681686, -0.376728, 1.376575,
+ 0.744338, 0.706498, -0.372844, 1.342935, 0.718799, 0.731258, -0.366649, 1.311052, 0.691756,
+ 0.755937, -0.359354, 1.280478, 0.662683, 0.779259, -0.350487, 1.250585, 0.632892, 0.803295,
+ -0.340941, 1.225722, 0.602160, 0.826570, -0.330174, 1.201003, 0.570520, 0.849954, -0.317854,
+ 1.178488, 0.537651, 0.873696, -0.304426, 1.158302, 0.503799, 0.896695, -0.290120, 1.139886,
+ 0.469645, 0.919149, -0.275106, 1.122884, 0.435625, 0.942121, -0.259282, 1.107691, 0.401228,
+ 0.964627, -0.242123, 1.093661, 0.367086, 0.986614, -0.224575, 1.081580, 0.332885, 1.009623,
+ -0.206837, 1.071375, 0.299209, 1.033126, -0.188092, 1.062241, 0.266187, 1.054954, -0.168637,
+ 1.052912, 0.233733, 1.077660, -0.149166, 1.047047, 0.203192, 1.097983, -0.128587, 1.041607,
+ 0.173918, 1.115586, -0.107339, 1.036850, 0.145531, 1.130170, -0.086203, 1.031427, 0.116890,
+ 1.141018, -0.064171, 1.024395, 0.087388, 1.147681, -0.042530, 1.015719, 0.057733, 1.152560,
+ -0.021011, 1.006883, 0.028413, 1.158406, 0.000158, 0.999897, -0.000106, 0.000200, -0.000195,
+ 1.950982, 0.975366, 0.000504, -0.000491, 1.950207, 0.975365, 0.002015, -0.001966, 1.950675,
+ 0.975362, 0.004535, -0.004423, 1.951281, 0.975370, 0.008062, -0.007863, 1.951045, 0.975362,
+ 0.012597, -0.012285, 1.951199, 0.975356, 0.018145, -0.017692, 1.951528, 0.975340, 0.024699,
+ -0.024074, 1.951194, 0.975321, 0.032266, -0.031434, 1.950865, 0.975288, 0.040853, -0.039771,
+ 1.951038, 0.975244, 0.050452, -0.049067, 1.950336, 0.975173, 0.061077, -0.059324, 1.949805,
+ 0.975078, 0.072736, -0.070526, 1.949133, 0.974951, 0.085431, -0.082528, 1.947947, 0.974777,
+ 0.099182, -0.095345, 1.946337, 0.974540, 0.113999, -0.109118, 1.944725, 0.974241, 0.129888,
+ -0.123741, 1.942857, 0.973852, 0.146842, -0.139071, 1.940251, 0.973342, 0.164890, -0.154986,
+ 1.937086, 0.972684, 0.184025, -0.171661, 1.933404, 0.971856, 0.204245, -0.188672, 1.928770,
+ 0.970785, 0.225528, -0.206252, 1.923041, 0.969448, 0.247841, -0.223972, 1.915788, 0.967742,
+ 0.271157, -0.241827, 1.907008, 0.965607, 0.295297, -0.259562, 1.895854, 0.963007, 0.320121,
+ -0.276909, 1.881289, 0.959722, 0.345566, -0.293883, 1.864528, 0.955831, 0.371012, -0.309816,
+ 1.842062, 0.951127, 0.396834, -0.325157, 1.818068, 0.945725, 0.422277, -0.339357, 1.788874,
+ 0.939318, 0.447928, -0.352387, 1.758283, 0.931470, 0.474315, -0.363680, 1.723668, 0.921900,
+ 0.501560, -0.372963, 1.686081, 0.909996, 0.528391, -0.380159, 1.645816, 0.896244, 0.554754,
+ -0.385545, 1.603709, 0.880326, 0.581888, -0.389778, 1.565475, 0.862716, 0.607791, -0.391839,
+ 1.524196, 0.843146, 0.633511, -0.392331, 1.483921, 0.821554, 0.658621, -0.391193, 1.445013,
+ 0.798336, 0.683160, -0.388424, 1.406963, 0.773299, 0.707429, -0.384104, 1.370996, 0.746668,
+ 0.732212, -0.377945, 1.335879, 0.717502, 0.756871, -0.369856, 1.302489, 0.686954, 0.781065,
+ -0.360707, 1.271815, 0.655372, 0.804167, -0.350091, 1.242416, 0.622683, 0.827948, -0.338941,
+ 1.217208, 0.589185, 0.850901, -0.326427, 1.192354, 0.555005, 0.873589, -0.312199, 1.169639,
+ 0.519594, 0.897085, -0.297374, 1.150181, 0.484105, 0.920459, -0.281932, 1.132858, 0.448661,
+ 0.942637, -0.265625, 1.115401, 0.413051, 0.965341, -0.248332, 1.101078, 0.377329, 0.987530,
+ -0.229983, 1.087377, 0.342349, 1.010739, -0.211647, 1.076582, 0.307824, 1.033449, -0.192725,
+ 1.065900, 0.273368, 1.055618, -0.172726, 1.056958, 0.240238, 1.079345, -0.152640, 1.049620,
+ 0.208322, 1.100058, -0.131931, 1.044084, 0.178242, 1.118547, -0.110351, 1.039387, 0.149493,
+ 1.132748, -0.088128, 1.033049, 0.119673, 1.143419, -0.066069, 1.025521, 0.089728, 1.150316,
+ -0.043513, 1.016378, 0.059253, 1.155208, -0.021593, 1.007506, 0.029140, 1.160871, 0.000111,
+ 0.999916, -0.000035, 0.000201, -0.000206, 2.061000, 1.025243, 0.000504, -0.000516, 2.049647,
+ 1.025237, 0.002015, -0.002066, 2.050169, 1.025237, 0.004535, -0.004650, 2.051254, 1.025255,
+ 0.008063, -0.008266, 2.051302, 1.025236, 0.012600, -0.012915, 2.051508, 1.025226, 0.018144,
+ -0.018594, 2.050981, 1.025215, 0.024700, -0.025304, 2.050841, 1.025190, 0.032267, -0.033038,
+ 2.050537, 1.025152, 0.040852, -0.041795, 2.050660, 1.025090, 0.050460, -0.051570, 2.049921,
+ 1.025017, 0.061094, -0.062347, 2.049350, 1.024908, 0.072762, -0.074111, 2.048517, 1.024760,
+ 0.085475, -0.086661, 2.047009, 1.024555, 0.099249, -0.100160, 2.045261, 1.024278, 0.114106,
+ -0.114628, 2.043508, 1.023941, 0.130032, -0.130002, 2.041321, 1.023488, 0.147050, -0.145985,
+ 2.038299, 1.022905, 0.165164, -0.162762, 2.034658, 1.022151, 0.184380, -0.180172, 2.030312,
+ 1.021200, 0.204704, -0.198022, 2.024944, 1.019966, 0.226129, -0.216359, 2.018546, 1.018424,
+ 0.248582, -0.234923, 2.010153, 1.016519, 0.272011, -0.253474, 1.999659, 1.014072, 0.296259,
+ -0.271820, 1.986076, 1.011071, 0.321423, -0.289959, 1.970618, 1.007389, 0.346897, -0.307283,
+ 1.949667, 1.002955, 0.372750, -0.323817, 1.925287, 0.997633, 0.398603, -0.339241, 1.896006,
+ 0.991354, 0.424351, -0.353633, 1.863658, 0.983937, 0.449887, -0.366660, 1.827430, 0.975254,
+ 0.475715, -0.378213, 1.789521, 0.964753, 0.502204, -0.387133, 1.745632, 0.951594, 0.530179,
+ -0.394976, 1.705347, 0.936344, 0.556732, -0.400134, 1.658928, 0.918907, 0.583123, -0.403439,
+ 1.613077, 0.899504, 0.609477, -0.405285, 1.567884, 0.878172, 0.634927, -0.405055, 1.523507,
+ 0.854396, 0.660357, -0.403494, 1.481712, 0.829259, 0.684851, -0.400104, 1.439000, 0.802359,
+ 0.709654, -0.395536, 1.400956, 0.773534, 0.733472, -0.388996, 1.362156, 0.743230, 0.757502,
+ -0.380263, 1.325113, 0.711090, 0.782249, -0.370594, 1.292913, 0.677166, 0.806017, -0.359509,
+ 1.262088, 0.642527, 0.828687, -0.347126, 1.232059, 0.607589, 0.852372, -0.334474, 1.207160,
+ 0.571938, 0.874266, -0.320074, 1.181978, 0.535518, 0.898168, -0.304719, 1.161156, 0.498375,
+ 0.920456, -0.288246, 1.140667, 0.461179, 0.942832, -0.271311, 1.122780, 0.424533, 0.966458,
+ -0.254154, 1.108743, 0.387784, 0.988907, -0.235659, 1.093872, 0.351689, 1.011557, -0.216322,
+ 1.081959, 0.315743, 1.035099, -0.197007, 1.070885, 0.280402, 1.056354, -0.176878, 1.059968,
+ 0.246472, 1.079854, -0.156058, 1.051815, 0.212818, 1.101494, -0.134772, 1.045757, 0.182143,
+ 1.120587, -0.113071, 1.041169, 0.152867, 1.135399, -0.090411, 1.034844, 0.122796, 1.146612,
+ -0.067477, 1.026974, 0.091888, 1.153168, -0.044849, 1.017303, 0.060779, 1.157912, -0.021998,
+ 1.007735, 0.029919, 1.163607, 0.000121, 0.999959, 0.000003, 0.000200, -0.000216, 2.163956,
+ 1.077737, 0.000504, -0.000543, 2.161128, 1.077732, 0.002016, -0.002173, 2.162732, 1.077729,
+ 0.004535, -0.004887, 2.161402, 1.077749, 0.008066, -0.008692, 2.163252, 1.077732, 0.012599,
+ -0.013576, 2.161300, 1.077727, 0.018145, -0.019546, 2.161151, 1.077702, 0.024702, -0.026599,
+ 2.161223, 1.077675, 0.032272, -0.034729, 2.160949, 1.077632, 0.040862, -0.043936, 2.160967,
+ 1.077575, 0.050470, -0.054203, 2.160035, 1.077473, 0.061113, -0.065528, 2.159490, 1.077348,
+ 0.072794, -0.077882, 2.158517, 1.077178, 0.085528, -0.091030, 2.156605, 1.076937, 0.099337,
+ -0.105251, 2.154828, 1.076631, 0.114228, -0.120456, 2.152812, 1.076229, 0.130202, -0.136573,
+ 2.150298, 1.075713, 0.147284, -0.153306, 2.146752, 1.075031, 0.165480, -0.170931, 2.142744,
+ 1.074173, 0.184793, -0.189083, 2.137475, 1.073063, 0.205224, -0.207840, 2.131320, 1.071683,
+ 0.226743, -0.226939, 2.123154, 1.069914, 0.249401, -0.246344, 2.114086, 1.067718, 0.272955,
+ -0.265640, 2.101599, 1.064924, 0.297494, -0.284846, 2.086612, 1.061512, 0.322731, -0.303452,
+ 2.067356, 1.057359, 0.348451, -0.321330, 2.043711, 1.052294, 0.374451, -0.338201, 2.015033,
+ 1.046153, 0.400454, -0.353816, 1.981139, 1.039003, 0.426434, -0.368216, 1.944128, 1.030498,
+ 0.452088, -0.381251, 1.903094, 1.020454, 0.477901, -0.392833, 1.860402, 1.008793, 0.504173,
+ -0.402408, 1.814402, 0.994791, 0.531520, -0.409545, 1.766273, 0.977733, 0.558049, -0.414351,
+ 1.714119, 0.958625, 0.584778, -0.417437, 1.664612, 0.937189, 0.610808, -0.418519, 1.613793,
+ 0.913543, 0.636915, -0.418094, 1.565942, 0.888137, 0.662204, -0.415742, 1.518783, 0.860728,
+ 0.686848, -0.411746, 1.473306, 0.831793, 0.710992, -0.406153, 1.430153, 0.800862, 0.735382,
+ -0.399519, 1.389824, 0.768768, 0.759079, -0.390927, 1.350744, 0.734825, 0.782912, -0.380111,
+ 1.313559, 0.699450, 0.806746, -0.368383, 1.280028, 0.663191, 0.830269, -0.355606, 1.249814,
+ 0.625927, 0.853305, -0.341988, 1.221138, 0.588644, 0.876326, -0.327545, 1.195837, 0.550849,
+ 0.898322, -0.311779, 1.171844, 0.512694, 0.921811, -0.294944, 1.150671, 0.474225, 0.944563,
+ -0.277333, 1.132224, 0.435772, 0.967089, -0.259340, 1.115422, 0.398001, 0.989754, -0.240836,
+ 1.100405, 0.360802, 1.012470, -0.221293, 1.086533, 0.323566, 1.036426, -0.201191, 1.075496,
+ 0.287387, 1.058709, -0.180590, 1.064233, 0.252184, 1.081593, -0.159810, 1.055296, 0.218441,
+ 1.103146, -0.137772, 1.047978, 0.186223, 1.122814, -0.115347, 1.042693, 0.156019, 1.137790,
+ -0.092582, 1.036049, 0.125579, 1.149184, -0.069152, 1.027944, 0.093986, 1.156062, -0.045661,
+ 1.018039, 0.062122, 1.160733, -0.022719, 1.008072, 0.030650, 1.166487, 0.000231, 1.000063,
+ -0.000120, 0.000201, -0.000228, 2.308308, 1.133128, 0.000504, -0.000571, 2.283756, 1.133123,
+ 0.002016, -0.002284, 2.283756, 1.133123, 0.004535, -0.005138, 2.283310, 1.133144, 0.008048,
+ -0.009119, 2.266192, 1.133138, 0.012600, -0.014274, 2.284377, 1.133110, 0.018147, -0.020553,
+ 2.284204, 1.133093, 0.024702, -0.027964, 2.283517, 1.133060, 0.032272, -0.036510, 2.282997,
+ 1.133007, 0.040866, -0.046188, 2.282986, 1.132930, 0.050481, -0.056979, 2.282260, 1.132824,
+ 0.061133, -0.068881, 2.281533, 1.132678, 0.072830, -0.081850, 2.280504, 1.132481, 0.085592,
+ -0.095657, 2.278304, 1.132202, 0.099431, -0.110594, 2.276269, 1.131845, 0.114360, -0.126590,
+ 2.273890, 1.131383, 0.130388, -0.143454, 2.270761, 1.130784, 0.147547, -0.161029, 2.266794,
+ 1.130003, 0.165836, -0.179523, 2.262332, 1.129016, 0.185269, -0.198527, 2.256326, 1.127738,
+ 0.205822, -0.218138, 2.249031, 1.126156, 0.227527, -0.238141, 2.239993, 1.124132, 0.250325,
+ -0.258302, 2.228878, 1.121594, 0.274070, -0.278329, 2.214204, 1.118449, 0.298793, -0.298310,
+ 2.196654, 1.114528, 0.324131, -0.317462, 2.173394, 1.109783, 0.350101, -0.335853, 2.146395,
+ 1.103901, 0.376293, -0.353064, 2.112341, 1.096954, 0.402547, -0.368950, 2.073700, 1.088642,
+ 0.428791, -0.383462, 2.031152, 1.078946, 0.454976, -0.396635, 1.986661, 1.067536, 0.480566,
+ -0.407873, 1.937038, 1.054403, 0.506154, -0.417303, 1.885155, 1.038894, 0.532862, -0.424194,
+ 1.830369, 1.020535, 0.560354, -0.429344, 1.776976, 0.999295, 0.587114, -0.431949, 1.721214,
+ 0.975990, 0.613345, -0.432547, 1.665739, 0.950239, 0.639335, -0.431338, 1.612200, 0.922467,
+ 0.664996, -0.428473, 1.561035, 0.892593, 0.688947, -0.423355, 1.508240, 0.861325, 0.713403,
+ -0.417235, 1.461776, 0.828289, 0.737649, -0.409848, 1.418888, 0.793863, 0.761275, -0.400901,
+ 1.376807, 0.758074, 0.784778, -0.390174, 1.337204, 0.721974, 0.808762, -0.377683, 1.301527,
+ 0.682718, 0.831993, -0.364037, 1.267144, 0.644001, 0.854696, -0.349494, 1.236023, 0.605478,
+ 0.877933, -0.334499, 1.209284, 0.565588, 0.900180, -0.318435, 1.183967, 0.526138, 0.923039,
+ -0.301669, 1.161513, 0.486524, 0.945895, -0.283298, 1.140838, 0.446747, 0.968069, -0.264438,
+ 1.122475, 0.408041, 0.991179, -0.245463, 1.106968, 0.369477, 1.012926, -0.225680, 1.091435,
+ 0.331626, 1.036995, -0.205401, 1.079561, 0.294288, 1.060909, -0.184310, 1.068215, 0.257696,
+ 1.083531, -0.162846, 1.058133, 0.223343, 1.105644, -0.141040, 1.050851, 0.190541, 1.125691,
+ -0.117965, 1.045001, 0.159310, 1.141297, -0.094377, 1.038028, 0.128238, 1.152672, -0.070831,
+ 1.029694, 0.096282, 1.159333, -0.046853, 1.019136, 0.063720, 1.163819, -0.022991, 1.008518,
+ 0.031234, 1.169564, 0.000125, 1.000069, -0.000024, 0.000202, -0.000241, 2.458341, 1.191742,
+ 0.000504, -0.000600, 2.418738, 1.191740, 0.002015, -0.002401, 2.418821, 1.191730, 0.004535,
+ -0.005405, 2.421986, 1.191756, 0.008071, -0.009618, 2.424988, 1.191753, 0.012600, -0.015012,
+ 2.420242, 1.191727, 0.018145, -0.021612, 2.419937, 1.191703, 0.024704, -0.029410, 2.419746,
+ 1.191662, 0.032278, -0.038398, 2.419409, 1.191604, 0.040874, -0.048574, 2.418995, 1.191515,
+ 0.050496, -0.059920, 2.418190, 1.191389, 0.061160, -0.072432, 2.417487, 1.191221, 0.072871,
+ -0.086009, 2.415853, 1.190984, 0.085664, -0.100559, 2.413669, 1.190664, 0.099543, -0.116283,
+ 2.411423, 1.190256, 0.114520, -0.133071, 2.408711, 1.189719, 0.130616, -0.150670, 2.404900,
+ 1.189019, 0.147856, -0.169197, 2.400512, 1.188125, 0.166235, -0.188545, 2.394939, 1.186972,
+ 0.185804, -0.208480, 2.388232, 1.185515, 0.206488, -0.228883, 2.379190, 1.183673, 0.228383,
+ -0.249897, 2.369208, 1.181382, 0.251305, -0.270851, 2.355459, 1.178478, 0.275349, -0.291780,
+ 2.339142, 1.174857, 0.300106, -0.312257, 2.316655, 1.170411, 0.325849, -0.332225, 2.291540,
+ 1.164883, 0.351782, -0.350862, 2.257242, 1.158196, 0.378248, -0.368431, 2.218671, 1.150173,
+ 0.404674, -0.384428, 2.173680, 1.140703, 0.431385, -0.399230, 2.127083, 1.129555, 0.457407,
+ -0.411875, 2.073236, 1.116436, 0.483275, -0.423013, 2.018223, 1.101373, 0.509278, -0.432624,
+ 1.962674, 1.084257, 0.534751, -0.439261, 1.900814, 1.064592, 0.561895, -0.443801, 1.839558,
+ 1.040881, 0.588677, -0.445872, 1.777763, 1.015208, 0.614900, -0.445896, 1.716550, 0.987252,
+ 0.641051, -0.444148, 1.657984, 0.957271, 0.666409, -0.440299, 1.600832, 0.924841, 0.691872,
+ -0.435318, 1.548237, 0.891185, 0.716638, -0.428631, 1.497572, 0.855929, 0.739864, -0.419872,
+ 1.447043, 0.819676, 0.763707, -0.410456, 1.403648, 0.781455, 0.786744, -0.399390, 1.360844,
+ 0.742965, 0.809585, -0.386381, 1.320529, 0.703260, 0.834164, -0.372622, 1.286467, 0.662385,
+ 0.856713, -0.357177, 1.252306, 0.621379, 0.879820, -0.341458, 1.223070, 0.580238, 0.902721,
+ -0.325024, 1.197115, 0.539028, 0.924650, -0.307543, 1.172314, 0.498592, 0.947613, -0.289557,
+ 1.151171, 0.457980, 0.969590, -0.269799, 1.129986, 0.417696, 0.992961, -0.250111, 1.113321,
+ 0.377529, 1.014582, -0.229761, 1.097149, 0.339096, 1.038069, -0.209375, 1.083913, 0.301119,
+ 1.061661, -0.188038, 1.071241, 0.263506, 1.085069, -0.165874, 1.060508, 0.227921, 1.107744,
+ -0.143437, 1.052930, 0.194062, 1.127982, -0.120574, 1.046396, 0.162506, 1.144541, -0.096569,
+ 1.039880, 0.130788, 1.155876, -0.072039, 1.030946, 0.098057, 1.162719, -0.047888, 1.020124,
+ 0.064956, 1.167089, -0.023740, 1.008953, 0.031966, 1.172775, 0.000277, 1.000067, -0.000111,
+ 0.000200, -0.000251, 2.573709, 1.253951, 0.000504, -0.000632, 2.572401, 1.253940, 0.002015,
+ -0.002527, 2.571267, 1.253927, 0.004535, -0.005687, 2.572481, 1.253948, 0.008062, -0.010108,
+ 2.571851, 1.253941, 0.012588, -0.015780, 2.568431, 1.253934, 0.018139, -0.022731, 2.569765,
+ 1.253893, 0.024709, -0.030948, 2.572115, 1.253853, 0.032283, -0.040401, 2.571456, 1.253785,
+ 0.040883, -0.051105, 2.571041, 1.253683, 0.050514, -0.063041, 2.570153, 1.253538, 0.061188,
+ -0.076195, 2.569085, 1.253336, 0.072926, -0.090402, 2.567184, 1.253065, 0.085746, -0.105745,
+ 2.564731, 1.252697, 0.099661, -0.122296, 2.561995, 1.252218, 0.114699, -0.139912, 2.559019,
+ 1.251590, 0.130882, -0.158362, 2.555017, 1.250766, 0.148202, -0.177856, 2.549419, 1.249744,
+ 0.166706, -0.198049, 2.542908, 1.248423, 0.186404, -0.219014, 2.535205, 1.246741, 0.207272,
+ -0.240376, 2.524893, 1.244596, 0.229345, -0.262230, 2.512804, 1.241917, 0.252494, -0.284134,
+ 2.496923, 1.238610, 0.276690, -0.305828, 2.476583, 1.234474, 0.301798, -0.327107, 2.451548,
+ 1.229292, 0.327423, -0.347300, 2.418630, 1.222997, 0.353848, -0.366699, 2.381002, 1.215366,
+ 0.380342, -0.384421, 2.334413, 1.206199, 0.407390, -0.400855, 2.285660, 1.195374, 0.433913,
+ -0.415241, 2.228604, 1.182290, 0.460837, -0.428275, 2.171532, 1.167385, 0.486381, -0.438573,
+ 2.105639, 1.150401, 0.511959, -0.447348, 2.040835, 1.130990, 0.537586, -0.454152, 1.974797,
+ 1.109302, 0.564035, -0.458684, 1.907895, 1.084131, 0.590690, -0.460058, 1.839482, 1.055803,
+ 0.617250, -0.459662, 1.772332, 1.025103, 0.643406, -0.457260, 1.707313, 0.992502, 0.668794,
+ -0.452666, 1.644722, 0.957657, 0.693930, -0.446641, 1.586832, 0.921340, 0.718708, -0.439121,
+ 1.531197, 0.883841, 0.743469, -0.430429, 1.480765, 0.844931, 0.766080, -0.419622, 1.430338,
+ 0.804786, 0.789801, -0.408368, 1.386295, 0.764206, 0.812718, -0.395392, 1.343758, 0.722565,
+ 0.835453, -0.380699, 1.304655, 0.680585, 0.858801, -0.364834, 1.269287, 0.637235, 0.881537,
+ -0.348092, 1.237493, 0.594579, 0.904656, -0.331087, 1.208862, 0.552313, 0.926357, -0.312966,
+ 1.182365, 0.510080, 0.949001, -0.294684, 1.159452, 0.468677, 0.971598, -0.275361, 1.138706,
+ 0.426723, 0.994905, -0.254947, 1.120552, 0.385875, 1.017981, -0.234109, 1.104215, 0.345751,
+ 1.040840, -0.213040, 1.089276, 0.306762, 1.063893, -0.191616, 1.075845, 0.269066, 1.086907,
+ -0.169272, 1.063788, 0.232171, 1.109937, -0.146076, 1.054977, 0.197826, 1.130808, -0.122544,
+ 1.048572, 0.165272, 1.146831, -0.098492, 1.040742, 0.133280, 1.158955, -0.073710, 1.031818,
+ 0.100262, 1.166161, -0.048610, 1.020747, 0.066165, 1.170491, -0.024209, 1.009380, 0.032741,
+ 1.176111, 0.000010, 1.000042, 0.000056, 0.000202, -0.000267, 2.786357, 1.320169, 0.000504,
+ -0.000665, 2.741889, 1.320168, 0.002015, -0.002660, 2.740000, 1.320143, 0.004536, -0.005987,
+ 2.744276, 1.320161, 0.008063, -0.010644, 2.743432, 1.320162, 0.012600, -0.016628, 2.741741,
+ 1.320148, 0.018144, -0.023937, 2.741314, 1.320127, 0.024708, -0.032577, 2.741916, 1.320061,
+ 0.032290, -0.042536, 2.742132, 1.319976, 0.040894, -0.053799, 2.741199, 1.319861, 0.050533,
+ -0.066361, 2.740258, 1.319691, 0.061223, -0.080202, 2.739045, 1.319458, 0.072985, -0.095109,
+ 2.736519, 1.319138, 0.085841, -0.111296, 2.733903, 1.318715, 0.099808, -0.128685, 2.730944,
+ 1.318156, 0.114903, -0.147202, 2.727293, 1.317424, 0.131164, -0.166575, 2.722169, 1.316485,
+ 0.148599, -0.187019, 2.716148, 1.315274, 0.167245, -0.208240, 2.708701, 1.313733, 0.187078,
+ -0.230151, 2.698998, 1.311792, 0.208153, -0.252538, 2.687341, 1.309343, 0.230418, -0.275295,
+ 2.672621, 1.306247, 0.253802, -0.298066, 2.653619, 1.302374, 0.278261, -0.320673, 2.629943,
+ 1.297573, 0.303527, -0.342528, 2.599228, 1.291625, 0.329571, -0.363531, 2.562226, 1.284374,
+ 0.355939, -0.382963, 2.515491, 1.275478, 0.382987, -0.401306, 2.464858, 1.264866, 0.409917,
+ -0.417455, 2.404877, 1.252184, 0.437015, -0.432067, 2.341408, 1.237415, 0.463474, -0.444204,
+ 2.271837, 1.220687, 0.489835, -0.454631, 2.200593, 1.200973, 0.516054, -0.463338, 2.129733,
+ 1.179346, 0.541397, -0.469425, 2.055635, 1.155039, 0.566798, -0.473526, 1.980812, 1.127866,
+ 0.593114, -0.474632, 1.904723, 1.097304, 0.619945, -0.473597, 1.832456, 1.063603, 0.646325,
+ -0.470656, 1.761501, 1.027971, 0.672320, -0.465675, 1.694248, 0.990692, 0.697163, -0.458527,
+ 1.629227, 0.951582, 0.721472, -0.449904, 1.568132, 0.911197, 0.745855, -0.440140, 1.512084,
+ 0.869745, 0.770089, -0.429338, 1.460694, 0.827648, 0.792546, -0.416701, 1.410739, 0.784728,
+ 0.815161, -0.403151, 1.365438, 0.741884, 0.837994, -0.388714, 1.324811, 0.697800, 0.861220,
+ -0.372573, 1.287723, 0.653341, 0.883737, -0.355024, 1.252491, 0.609455, 0.906784, -0.337092,
+ 1.221844, 0.565275, 0.928493, -0.318370, 1.192881, 0.521558, 0.951495, -0.299605, 1.169131,
+ 0.478149, 0.973586, -0.280067, 1.146316, 0.436325, 0.996400, -0.259823, 1.127860, 0.394409,
+ 1.019780, -0.238313, 1.110521, 0.353045, 1.042775, -0.216506, 1.093915, 0.312803, 1.066822,
+ -0.194695, 1.080326, 0.274100, 1.089869, -0.172290, 1.067722, 0.236657, 1.113606, -0.149264,
+ 1.058471, 0.201603, 1.134229, -0.124814, 1.050701, 0.168398, 1.150922, -0.100070, 1.043051,
+ 0.135616, 1.163224, -0.075155, 1.033742, 0.102144, 1.169965, -0.049933, 1.021818, 0.067532,
+ 1.174200, -0.024461, 1.009916, 0.033215, 1.179766, 0.000188, 1.000045, -0.000014, 0.000202,
+ -0.000281, 2.964186, 1.390880, 0.000505, -0.000702, 2.945157, 1.390903, 0.002015, -0.002802,
+ 2.931184, 1.390863, 0.004535, -0.006307, 2.935673, 1.390900, 0.008063, -0.011213, 2.934274,
+ 1.390890, 0.012598, -0.017516, 2.932216, 1.390876, 0.018147, -0.025221, 2.933324, 1.390832,
+ 0.024711, -0.034322, 2.933945, 1.390769, 0.032295, -0.044810, 2.933496, 1.390674, 0.040904,
+ -0.056673, 2.932487, 1.390538, 0.050555, -0.069906, 2.931571, 1.390342, 0.061259, -0.084468,
+ 2.929914, 1.390064, 0.073053, -0.100152, 2.927039, 1.389695, 0.085948, -0.117202, 2.924241,
+ 1.389201, 0.099968, -0.135531, 2.920760, 1.388548, 0.115135, -0.154906, 2.915998, 1.387692,
+ 0.131496, -0.175352, 2.910285, 1.386611, 0.149049, -0.196783, 2.903174, 1.385190, 0.167848,
+ -0.219066, 2.894584, 1.383407, 0.187879, -0.241983, 2.883171, 1.381148, 0.209143, -0.265398,
+ 2.869102, 1.378261, 0.231689, -0.289254, 2.852238, 1.374690, 0.255223, -0.312776, 2.828264,
+ 1.370166, 0.279952, -0.336260, 2.800175, 1.364591, 0.305572, -0.358865, 2.764282, 1.357758,
+ 0.331650, -0.380223, 2.717845, 1.349413, 0.358491, -0.400252, 2.665326, 1.339084, 0.385445,
+ -0.418422, 2.602293, 1.326773, 0.412947, -0.434993, 2.536973, 1.312141, 0.439681, -0.448757,
+ 2.459463, 1.295205, 0.467272, -0.461427, 2.386250, 1.275573, 0.493568, -0.471102, 2.303225,
+ 1.253400, 0.519743, -0.478930, 2.221945, 1.228890, 0.544882, -0.484098, 2.136425, 1.201730,
+ 0.570690, -0.488125, 2.057093, 1.172022, 0.595905, -0.489185, 1.975334, 1.139312, 0.622747,
+ -0.487535, 1.895055, 1.103038, 0.648695, -0.483482, 1.815995, 1.064364, 0.675159, -0.478096,
+ 1.744272, 1.024098, 0.700714, -0.470492, 1.675257, 0.982186, 0.725641, -0.461398, 1.609135,
+ 0.939137, 0.748552, -0.449825, 1.545091, 0.894791, 0.772808, -0.438185, 1.489394, 0.850373,
+ 0.795928, -0.425073, 1.437026, 0.805287, 0.818900, -0.411028, 1.389654, 0.760003, 0.841633,
+ -0.396047, 1.345873, 0.714914, 0.863213, -0.379637, 1.305185, 0.669271, 0.886662, -0.362227,
+ 1.269147, 0.622935, 0.908504, -0.343068, 1.234714, 0.577757, 0.931425, -0.323982, 1.204997,
+ 0.532922, 0.953835, -0.304347, 1.178871, 0.488154, 0.975813, -0.284219, 1.155019, 0.444885,
+ 0.997662, -0.263544, 1.133941, 0.402224, 1.021167, -0.242611, 1.116100, 0.360530, 1.044038,
+ -0.220065, 1.098348, 0.318968, 1.068837, -0.197580, 1.084605, 0.279107, 1.092548, -0.174779,
+ 1.071217, 0.241111, 1.116157, -0.151596, 1.060486, 0.204913, 1.137486, -0.127478, 1.052751,
+ 0.171410, 1.154694, -0.101915, 1.044807, 0.137999, 1.166867, -0.076246, 1.034824, 0.103807,
+ 1.173715, -0.050661, 1.022501, 0.068802, 1.178236, -0.025355, 1.010324, 0.034155, 1.183545,
+ 0.000205, 1.000059, -0.000110, 0.000201, -0.000294, 3.161080, 1.466721, 0.000505, -0.000740,
+ 3.155526, 1.466737, 0.002016, -0.002957, 3.152852, 1.466688, 0.004537, -0.006655, 3.150654,
+ 1.466667, 0.008066, -0.011828, 3.153109, 1.466694, 0.012604, -0.018479, 3.152143, 1.466721,
+ 0.018150, -0.026598, 3.151025, 1.466636, 0.024714, -0.036191, 3.150300, 1.466562, 0.032301,
+ -0.047249, 3.149861, 1.466450, 0.040924, -0.059766, 3.149548, 1.466289, 0.050579, -0.073703,
+ 3.147516, 1.466055, 0.061306, -0.089022, 3.145680, 1.465738, 0.073135, -0.105563, 3.142428,
+ 1.465301, 0.086075, -0.123544, 3.139113, 1.464715, 0.100153, -0.142853, 3.135064, 1.463956,
+ 0.115411, -0.163183, 3.129509, 1.462962, 0.131876, -0.184760, 3.122959, 1.461670, 0.149570,
+ -0.207172, 3.114153, 1.460045, 0.168523, -0.230578, 3.103626, 1.457945, 0.188784, -0.254658,
+ 3.090818, 1.455279, 0.210264, -0.279114, 3.073352, 1.451998, 0.233030, -0.303930, 3.052592,
+ 1.447780, 0.256959, -0.328517, 3.025187, 1.442568, 0.281901, -0.352755, 2.990341, 1.436026,
+ 0.307728, -0.375894, 2.946820, 1.427979, 0.334197, -0.397924, 2.892845, 1.418249, 0.360966,
+ -0.417914, 2.827937, 1.406370, 0.388478, -0.436526, 2.758006, 1.392134, 0.415567, -0.452366,
+ 2.674696, 1.375244, 0.443518, -0.466917, 2.595136, 1.355660, 0.470631, -0.478417, 2.504173,
+ 1.333123, 0.497419, -0.487825, 2.413227, 1.308181, 0.523961, -0.495064, 2.321239, 1.280227,
+ 0.549708, -0.499844, 2.228911, 1.249894, 0.575296, -0.502844, 2.138834, 1.217130, 0.600168,
+ -0.503368, 2.049030, 1.181412, 0.625874, -0.501622, 1.962267, 1.142648, 0.652164, -0.496936,
+ 1.876900, 1.101268, 0.678029, -0.490319, 1.796344, 1.057782, 0.703248, -0.481575, 1.718925,
+ 1.012884, 0.728520, -0.471822, 1.648358, 0.966487, 0.752577, -0.460134, 1.581989, 0.919880,
+ 0.776163, -0.447164, 1.520109, 0.873087, 0.800016, -0.433601, 1.465081, 0.825803, 0.822176,
+ -0.418388, 1.412564, 0.778249, 0.844873, -0.402704, 1.366184, 0.730849, 0.865955, -0.385633,
+ 1.321865, 0.684037, 0.888173, -0.368255, 1.283464, 0.637192, 0.910994, -0.349332, 1.249215,
+ 0.590131, 0.934270, -0.329612, 1.218366, 0.543213, 0.956653, -0.309228, 1.189808, 0.497752,
+ 0.978476, -0.288310, 1.163674, 0.452837, 1.000755, -0.267243, 1.141389, 0.409481, 1.023827,
+ -0.246015, 1.122012, 0.367354, 1.045572, -0.223777, 1.103303, 0.325171, 1.070445, -0.200837,
+ 1.088010, 0.284442, 1.094268, -0.177211, 1.073650, 0.245138, 1.118639, -0.153531, 1.063051,
+ 0.208289, 1.139786, -0.129074, 1.053921, 0.173607, 1.157848, -0.104051, 1.045968, 0.140467,
+ 1.170697, -0.077694, 1.035782, 0.105594, 1.177874, -0.051393, 1.023483, 0.069898, 1.182242,
+ -0.025392, 1.010620, 0.034532, 1.187612, -0.000032, 1.000062, -0.000035, 0.000202, -0.000313,
+ 3.450327, 1.548291, 0.000504, -0.000780, 3.396162, 1.548289, 0.002015, -0.003120, 3.395621,
+ 1.548260, 0.004533, -0.007019, 3.394299, 1.548217, 0.008066, -0.012486, 3.398803, 1.548274,
+ 0.012600, -0.019500, 3.396363, 1.548245, 0.018151, -0.028076, 3.396805, 1.548192, 0.024722,
+ -0.038209, 3.396384, 1.548109, 0.032306, -0.049868, 3.395158, 1.547979, 0.040936, -0.063077,
+ 3.394303, 1.547785, 0.050610, -0.077791, 3.392979, 1.547513, 0.061360, -0.093869, 3.389910,
+ 1.547134, 0.073227, -0.111380, 3.386669, 1.546619, 0.086217, -0.130371, 3.382974, 1.545938,
+ 0.100364, -0.150684, 3.378046, 1.545039, 0.115733, -0.172116, 3.371719, 1.543880, 0.132309,
+ -0.194809, 3.363764, 1.542380, 0.150174, -0.218431, 3.353699, 1.540462, 0.169340, -0.242954,
+ 3.341397, 1.538002, 0.189788, -0.268175, 3.324957, 1.534894, 0.211581, -0.293776, 3.304776,
+ 1.530954, 0.234561, -0.319619, 3.278192, 1.526033, 0.258776, -0.345089, 3.244910, 1.519926,
+ 0.284059, -0.370176, 3.203338, 1.512296, 0.310312, -0.394171, 3.152477, 1.502956, 0.336748,
+ -0.416137, 3.083616, 1.491463, 0.364029, -0.436752, 3.010481, 1.477493, 0.391575, -0.455102,
+ 2.925454, 1.460933, 0.419409, -0.471378, 2.834380, 1.441554, 0.446811, -0.484714, 2.733329,
+ 1.418861, 0.474489, -0.496021, 2.633630, 1.393405, 0.501751, -0.504991, 2.530935, 1.364633,
+ 0.528488, -0.511392, 2.426653, 1.333234, 0.554428, -0.515395, 2.323633, 1.299138, 0.580434,
+ -0.517761, 2.224964, 1.262462, 0.605474, -0.517598, 2.127228, 1.223784, 0.629888, -0.514946,
+ 2.030545, 1.182321, 0.655579, -0.510177, 1.939070, 1.138515, 0.681940, -0.503097, 1.852355,
+ 1.091502, 0.707228, -0.493537, 1.768084, 1.043464, 0.731894, -0.482372, 1.690840, 0.994242,
+ 0.756741, -0.470312, 1.619277, 0.944749, 0.780160, -0.456412, 1.553430, 0.894816, 0.803384,
+ -0.441492, 1.493357, 0.845202, 0.826347, -0.425944, 1.437830, 0.795954, 0.849145, -0.409532,
+ 1.388578, 0.746915, 0.870617, -0.391988, 1.341527, 0.698025, 0.892943, -0.374229, 1.302188,
+ 0.649579, 0.913828, -0.355148, 1.262877, 0.601833, 0.936830, -0.335238, 1.230136, 0.554521,
+ 0.958687, -0.313939, 1.199596, 0.507208, 0.982008, -0.292741, 1.173619, 0.461357, 1.003691,
+ -0.270940, 1.149015, 0.416031, 1.027223, -0.249102, 1.128689, 0.372457, 1.050048, -0.226899,
+ 1.109444, 0.330281, 1.074105, -0.204329, 1.092943, 0.288987, 1.098971, -0.180560, 1.078591,
+ 0.249075, 1.123324, -0.155987, 1.066885, 0.211519, 1.145445, -0.130929, 1.057617, 0.176506,
+ 1.162856, -0.105269, 1.048453, 0.142345, 1.175360, -0.079267, 1.037439, 0.107452, 1.182514,
+ -0.052547, 1.024393, 0.071252, 1.186575, -0.025744, 1.011093, 0.035019, 1.192050, 0.000318,
+ 1.000013, -0.000152, 0.000204, -0.000334, 3.909175, 1.636412, 0.000504, -0.000825, 3.678647,
+ 1.636410, 0.002015, -0.003298, 3.678315, 1.636387, 0.004533, -0.007417, 3.674126, 1.636310,
+ 0.008062, -0.013190, 3.676771, 1.636376, 0.012603, -0.020613, 3.678135, 1.636369, 0.018153,
+ -0.029675, 3.677315, 1.636299, 0.024723, -0.040378, 3.676872, 1.636196, 0.032318, -0.052708,
+ 3.675750, 1.636038, 0.040955, -0.066660, 3.674803, 1.635810, 0.050645, -0.082203, 3.672735,
+ 1.635494, 0.061429, -0.099150, 3.669047, 1.635048, 0.073333, -0.117679, 3.665401, 1.634437,
+ 0.086388, -0.137725, 3.661315, 1.633634, 0.100620, -0.159081, 3.654992, 1.632571, 0.116087,
+ -0.181721, 3.647341, 1.631202, 0.132820, -0.205611, 3.637877, 1.629432, 0.150867, -0.230542,
+ 3.626333, 1.627161, 0.170234, -0.256239, 3.610671, 1.624266, 0.190981, -0.282751, 3.591685,
+ 1.620589, 0.213013, -0.309430, 3.565864, 1.615999, 0.236387, -0.336427, 3.534826, 1.610216,
+ 0.260943, -0.362931, 3.493984, 1.603047, 0.286497, -0.388644, 3.442075, 1.593920, 0.312769,
+ -0.412912, 3.375973, 1.582961, 0.339832, -0.435635, 3.299355, 1.569343, 0.367214, -0.456181,
+ 3.208994, 1.553137, 0.394935, -0.474325, 3.108910, 1.533791, 0.422935, -0.490318, 3.001767,
+ 1.511093, 0.451166, -0.503827, 2.891735, 1.485145, 0.478695, -0.514185, 2.773430, 1.455617,
+ 0.506313, -0.522502, 2.657639, 1.422946, 0.533427, -0.528119, 2.541132, 1.387843, 0.559942,
+ -0.531430, 2.426950, 1.349542, 0.585150, -0.531978, 2.312437, 1.309303, 0.610500, -0.531054,
+ 2.205966, 1.266280, 0.635380, -0.528058, 2.101993, 1.221709, 0.659852, -0.522751, 2.002950,
+ 1.175062, 0.685151, -0.515026, 1.908647, 1.125078, 0.710920, -0.505020, 1.819389, 1.074296,
+ 0.736066, -0.493268, 1.735806, 1.022420, 0.760503, -0.480032, 1.658607, 0.970230, 0.785091,
+ -0.465986, 1.589424, 0.917077, 0.807523, -0.449721, 1.522533, 0.864888, 0.830974, -0.433461,
+ 1.465416, 0.813006, 0.852659, -0.415808, 1.409076, 0.761689, 0.874841, -0.397855, 1.360758,
+ 0.711258, 0.896322, -0.379041, 1.316829, 0.661721, 0.918134, -0.360048, 1.278574, 0.612263,
+ 0.939356, -0.340108, 1.242200, 0.564369, 0.961025, -0.318877, 1.210305, 0.516506, 0.984371,
+ -0.297130, 1.183689, 0.469342, 1.006905, -0.274661, 1.157466, 0.423080, 1.029941, -0.252234,
+ 1.135066, 0.378315, 1.052751, -0.229268, 1.114518, 0.335169, 1.077981, -0.206662, 1.097760,
+ 0.293336, 1.102542, -0.183331, 1.082051, 0.252984, 1.126539, -0.158797, 1.068935, 0.214990,
+ 1.149023, -0.133014, 1.058996, 0.178903, 1.167550, -0.106641, 1.050245, 0.144559, 1.179994,
+ -0.079952, 1.038648, 0.108667, 1.187104, -0.053316, 1.025284, 0.072209, 1.191406, -0.026826,
+ 1.011453, 0.035833, 1.196748, 0.000226, 1.000034, -0.000061, 0.000200, -0.000346, 3.996419,
+ 1.732034, 0.000504, -0.000873, 4.000138, 1.732038, 0.002016, -0.003492, 4.002078, 1.732012,
+ 0.004538, -0.007859, 4.005626, 1.731962, 0.008064, -0.013963, 3.998500, 1.731999, 0.012590,
+ -0.021794, 3.995024, 1.732004, 0.018154, -0.031406, 3.999233, 1.731901, 0.024727, -0.042733,
+ 3.998497, 1.731774, 0.032327, -0.055781, 3.997064, 1.731599, 0.040974, -0.070543, 3.995856,
+ 1.731325, 0.050685, -0.086984, 3.993839, 1.730945, 0.061506, -0.104897, 3.989519, 1.730417,
+ 0.073458, -0.124506, 3.985313, 1.729697, 0.086573, -0.145706, 3.979984, 1.728747, 0.100909,
+ -0.168211, 3.972562, 1.727491, 0.116509, -0.192198, 3.963836, 1.725854, 0.133404, -0.217280,
+ 3.951919, 1.723749, 0.151659, -0.243556, 3.937734, 1.721093, 0.171288, -0.270611, 3.919021,
+ 1.717640, 0.192301, -0.298389, 3.895171, 1.713272, 0.214683, -0.326338, 3.864171, 1.707825,
+ 0.238392, -0.354394, 3.824682, 1.700956, 0.263151, -0.381636, 3.771168, 1.692392, 0.289155,
+ -0.408266, 3.709961, 1.681769, 0.315832, -0.433070, 3.630302, 1.668539, 0.342942, -0.455741,
+ 3.534719, 1.652513, 0.370892, -0.476655, 3.431531, 1.633428, 0.398985, -0.494692, 3.314933,
+ 1.610694, 0.427206, -0.510313, 3.189741, 1.584240, 0.455266, -0.522760, 3.058325, 1.554195,
+ 0.483472, -0.532872, 2.927213, 1.520805, 0.511192, -0.540229, 2.794112, 1.484026, 0.538706,
+ -0.545105, 2.663786, 1.443796, 0.565422, -0.547251, 2.534841, 1.401429, 0.591270, -0.547115,
+ 2.408437, 1.356231, 0.616787, -0.545113, 2.291284, 1.308887, 0.641380, -0.540853, 2.177478,
+ 1.260447, 0.665344, -0.534561, 2.069265, 1.210634, 0.690147, -0.527115, 1.969776, 1.158569,
+ 0.714578, -0.516171, 1.870847, 1.104593, 0.740349, -0.504048, 1.782674, 1.049578, 0.764563,
+ -0.489683, 1.698614, 0.994458, 0.788710, -0.474541, 1.624447, 0.938612, 0.812154, -0.458099,
+ 1.554453, 0.883694, 0.834566, -0.440345, 1.490045, 0.830220, 0.857486, -0.422491, 1.432889,
+ 0.776499, 0.879224, -0.403588, 1.380669, 0.724257, 0.899971, -0.383819, 1.333124, 0.673311,
+ 0.922111, -0.364250, 1.292648, 0.622999, 0.942842, -0.343873, 1.253933, 0.573304, 0.964398,
+ -0.323206, 1.221027, 0.525090, 0.986860, -0.301711, 1.191806, 0.477580, 1.009760, -0.278695,
+ 1.165162, 0.430624, 1.033347, -0.255591, 1.141715, 0.384482, 1.055937, -0.232039, 1.119739,
+ 0.340532, 1.081178, -0.208664, 1.102117, 0.297311, 1.105696, -0.184935, 1.085062, 0.256227,
+ 1.129575, -0.160673, 1.070918, 0.217709, 1.152135, -0.135414, 1.060642, 0.181471, 1.171221,
+ -0.108462, 1.051041, 0.146380, 1.184412, -0.081008, 1.039694, 0.110120, 1.191820, -0.053710,
+ 1.025903, 0.073052, 1.196195, -0.026625, 1.011816, 0.036129, 1.201677, -0.000175, 0.999945,
+ 0.000098, 0.000196, -0.000360, 4.100786, 1.836290, 0.000504, -0.000925, 4.370184, 1.836295,
+ 0.002018, -0.003706, 4.385247, 1.836243, 0.004534, -0.008324, 4.370146, 1.836210, 0.008064,
+ -0.014805, 4.372335, 1.836256, 0.012597, -0.023116, 4.359918, 1.836259, 0.018158, -0.033299,
+ 4.371503, 1.836123, 0.024732, -0.045301, 4.370533, 1.835988, 0.032344, -0.059143, 4.369649,
+ 1.835768, 0.040999, -0.074779, 4.367861, 1.835454, 0.050739, -0.092178, 4.364322, 1.834974,
+ 0.061594, -0.111161, 4.359221, 1.834355, 0.073604, -0.131958, 4.354620, 1.833499, 0.086796,
+ -0.154393, 4.347915, 1.832355, 0.101246, -0.178201, 4.339152, 1.830880, 0.116990, -0.203531,
+ 4.328327, 1.828936, 0.134086, -0.230043, 4.314240, 1.826442, 0.152589, -0.257718, 4.296795,
+ 1.823230, 0.172514, -0.286176, 4.273985, 1.819124, 0.193853, -0.315295, 4.244136, 1.813909,
+ 0.216582, -0.344507, 4.205152, 1.807410, 0.240668, -0.373646, 4.154781, 1.799084, 0.265904,
+ -0.401897, 4.091563, 1.788905, 0.292226, -0.429136, 4.013199, 1.776206, 0.319045, -0.454057,
+ 3.912886, 1.760500, 0.346721, -0.477219, 3.800927, 1.741586, 0.374849, -0.497883, 3.675652,
+ 1.718818, 0.403078, -0.515504, 3.536892, 1.692138, 0.431597, -0.530621, 3.391351, 1.661434,
+ 0.460246, -0.542852, 3.242817, 1.626989, 0.488899, -0.552238, 3.093685, 1.588582, 0.517215,
+ -0.559045, 2.944163, 1.546300, 0.544480, -0.562351, 2.794189, 1.501299, 0.571542, -0.563394,
+ 2.650239, 1.453758, 0.598167, -0.562590, 2.513757, 1.403321, 0.624104, -0.559636, 2.384203,
+ 1.352431, 0.648789, -0.554148, 2.259149, 1.298758, 0.672715, -0.546779, 2.140250, 1.244943,
+ 0.696258, -0.537896, 2.030401, 1.189971, 0.720048, -0.527401, 1.928311, 1.134526, 0.744078,
+ -0.514142, 1.830175, 1.076504, 0.768895, -0.499352, 1.740731, 1.018032, 0.792551, -0.482982,
+ 1.658911, 0.960250, 0.817007, -0.466406, 1.586579, 0.903029, 0.839035, -0.447616, 1.516969,
+ 0.846484, 0.862742, -0.429261, 1.458675, 0.791420, 0.884307, -0.409479, 1.402989, 0.737125,
+ 0.905641, -0.389303, 1.352817, 0.683912, 0.926185, -0.368344, 1.306684, 0.632690, 0.947229,
+ -0.347366, 1.267395, 0.581739, 0.969502, -0.326720, 1.233192, 0.532305, 0.990758, -0.304973,
+ 1.201017, 0.484166, 1.012749, -0.282816, 1.173018, 0.437385, 1.035533, -0.259084, 1.147184,
+ 0.390755, 1.059915, -0.235239, 1.125388, 0.345399, 1.084348, -0.211044, 1.105859, 0.301356,
+ 1.109544, -0.186698, 1.088888, 0.259708, 1.133770, -0.161900, 1.073848, 0.220324, 1.157553,
+ -0.136604, 1.063190, 0.183857, 1.176461, -0.110428, 1.053110, 0.148521, 1.190137, -0.082898,
+ 1.041484, 0.112124, 1.197215, -0.054554, 1.026844, 0.074160, 1.201654, -0.026744, 1.012264,
+ 0.036527, 1.207085, 0.000399, 1.000034, -0.000201, 0.000191, -0.000373, 4.194318, 1.950551,
+ 0.000504, -0.000983, 4.804350, 1.950552, 0.002015, -0.003931, 4.802820, 1.950518, 0.004536,
+ -0.008847, 4.805254, 1.950472, 0.008064, -0.015725, 4.804152, 1.950517, 0.012693, -0.024740,
+ 4.826828, 1.949914, 0.018159, -0.035365, 4.803103, 1.950349, 0.024740, -0.048122, 4.803220,
+ 1.950183, 0.032361, -0.062822, 4.801522, 1.949917, 0.041034, -0.079430, 4.799593, 1.949538,
+ 0.050815, -0.097841, 4.797179, 1.948972, 0.061702, -0.118026, 4.789557, 1.948246, 0.073766,
+ -0.140112, 4.783293, 1.947204, 0.087066, -0.163819, 4.775698, 1.945855, 0.101637, -0.189122,
+ 4.764612, 1.944052, 0.117558, -0.215884, 4.751486, 1.941710, 0.134884, -0.243968, 4.734791,
+ 1.938727, 0.153637, -0.273170, 4.712078, 1.934891, 0.173890, -0.303146, 4.683575, 1.929976,
+ 0.195643, -0.333704, 4.646766, 1.923740, 0.218767, -0.364170, 4.596814, 1.915888, 0.243337,
+ -0.394530, 4.535509, 1.905970, 0.268860, -0.423512, 4.452006, 1.893623, 0.295173, -0.450609,
+ 4.345682, 1.878286, 0.322784, -0.476488, 4.231632, 1.859391, 0.350616, -0.499420, 4.093553,
+ 1.836912, 0.379127, -0.519862, 3.944127, 1.809625, 0.407860, -0.537373, 3.782223, 1.778529,
+ 0.436717, -0.551802, 3.615563, 1.742684, 0.465345, -0.562951, 3.440672, 1.702289, 0.494158,
+ -0.571334, 3.268070, 1.658666, 0.522896, -0.577227, 3.100668, 1.611027, 0.551379, -0.580514,
+ 2.937615, 1.559742, 0.578992, -0.580610, 2.778703, 1.507257, 0.605095, -0.577729, 2.621626,
+ 1.451941, 0.630653, -0.573000, 2.476506, 1.395218, 0.656175, -0.566944, 2.341592, 1.337862,
+ 0.681036, -0.558988, 2.216478, 1.279275, 0.704713, -0.549211, 2.096972, 1.220526, 0.726894,
+ -0.537190, 1.983311, 1.161709, 0.749865, -0.524167, 1.881100, 1.102095, 0.773553, -0.508991,
+ 1.785637, 1.042039, 0.797102, -0.491658, 1.697234, 0.981588, 0.821187, -0.474093, 1.620250,
+ 0.921265, 0.843848, -0.454980, 1.547071, 0.862757, 0.866662, -0.435421, 1.482008, 0.804700,
+ 0.888696, -0.414990, 1.424116, 0.749432, 0.910945, -0.394472, 1.372658, 0.694767, 0.932300,
+ -0.373239, 1.325157, 0.641106, 0.952850, -0.351347, 1.282217, 0.589689, 0.974718, -0.329809,
+ 1.244897, 0.539322, 0.996445, -0.307902, 1.212306, 0.490083, 1.017580, -0.285392, 1.181402,
+ 0.442702, 1.040342, -0.262782, 1.155996, 0.395911, 1.064399, -0.238995, 1.131708, 0.350206,
+ 1.089464, -0.214297, 1.111215, 0.305175, 1.115565, -0.189293, 1.093094, 0.262686, 1.140640,
+ -0.163843, 1.077994, 0.223078, 1.163824, -0.137789, 1.066014, 0.185651, 1.182577, -0.111087,
+ 1.055615, 0.150045, 1.195775, -0.083945, 1.042940, 0.113457, 1.203175, -0.056145, 1.028015,
+ 0.075453, 1.207282, -0.027685, 1.012552, 0.037217, 1.213019, 0.000362, 0.999938, -0.000293,
+ 0.000187, -0.000388, 4.316009, 2.076500, 0.000504, -0.001048, 5.317799, 2.076499, 0.002014,
+ -0.004182, 5.306557, 2.076523, 0.004539, -0.009425, 5.317505, 2.076453, 0.008063, -0.016737,
+ 5.312143, 2.076410, 0.012614, -0.026171, 5.316434, 2.076389, 0.018158, -0.037641, 5.307836,
+ 2.076265, 0.024767, -0.051266, 5.315297, 2.076044, 0.032372, -0.066859, 5.307433, 2.075743,
+ 0.041066, -0.084538, 5.304809, 2.075270, 0.050871, -0.104062, 5.299277, 2.074622, 0.061821,
+ -0.125613, 5.293419, 2.073708, 0.073970, -0.149085, 5.286629, 2.072457, 0.087375, -0.174214,
+ 5.275937, 2.070804, 0.102105, -0.201136, 5.263267, 2.068647, 0.118223, -0.229505, 5.246309,
+ 2.065846, 0.135814, -0.259217, 5.225496, 2.062189, 0.154887, -0.289990, 5.196580, 2.057566,
+ 0.175510, -0.321618, 5.160716, 2.051593, 0.197636, -0.353632, 5.112202, 2.043949, 0.221168,
+ -0.385303, 5.046981, 2.034445, 0.246099, -0.416511, 4.965386, 2.022368, 0.272070, -0.446377,
+ 4.860735, 2.007160, 0.299090, -0.474279, 4.735140, 1.988598, 0.326702, -0.499809, 4.584962,
+ 1.965865, 0.355017, -0.522790, 4.420447, 1.938705, 0.383856, -0.542755, 4.241942, 1.906370,
+ 0.413059, -0.559903, 4.053302, 1.869455, 0.441882, -0.573174, 3.852753, 1.827946, 0.471516,
+ -0.584151, 3.660377, 1.781652, 0.500872, -0.591843, 3.466027, 1.730885, 0.529677, -0.596253,
+ 3.272812, 1.676821, 0.557683, -0.597604, 3.084286, 1.620064, 0.585652, -0.596591, 2.906111,
+ 1.560909, 0.612819, -0.593138, 2.738258, 1.500318, 0.639848, -0.588245, 2.584172, 1.438127,
+ 0.664758, -0.580140, 2.430697, 1.375746, 0.688754, -0.570189, 2.290701, 1.312727, 0.712848,
+ -0.559420, 2.162679, 1.250063, 0.735111, -0.546570, 2.042186, 1.187840, 0.757521, -0.532944,
+ 1.933435, 1.125513, 0.780056, -0.517981, 1.833524, 1.063827, 0.802513, -0.500724, 1.739053,
+ 1.002154, 0.825462, -0.481625, 1.652381, 0.939811, 0.848973, -0.462327, 1.577560, 0.878279,
+ 0.871521, -0.441928, 1.509291, 0.819200, 0.892325, -0.420297, 1.443799, 0.761607, 0.914935,
+ -0.399072, 1.389647, 0.705351, 0.936429, -0.377232, 1.339903, 0.650213, 0.957614, -0.355091,
+ 1.295467, 0.597773, 0.979578, -0.332767, 1.256692, 0.545914, 1.000860, -0.310147, 1.221666,
+ 0.495661, 1.022550, -0.287395, 1.190775, 0.448026, 1.045005, -0.264582, 1.162641, 0.400490,
+ 1.068703, -0.241464, 1.138358, 0.354088, 1.093098, -0.217504, 1.115973, 0.309812, 1.119230,
+ -0.192140, 1.096284, 0.266297, 1.144608, -0.165975, 1.080042, 0.225831, 1.168599, -0.139174,
+ 1.067749, 0.187761, 1.187970, -0.111910, 1.056635, 0.151322, 1.201240, -0.083978, 1.043566,
+ 0.114337, 1.208895, -0.056089, 1.028366, 0.076083, 1.213344, -0.028369, 1.013074, 0.037735,
+ 1.219220, -0.000534, 0.999968, 0.000076, 0.000182, -0.000404, 4.433519, 2.216201, 0.000504,
+ -0.001117, 5.911693, 2.216198, 0.002017, -0.004469, 5.919142, 2.216190, 0.004536, -0.010051,
+ 5.913172, 2.216130, 0.008065, -0.017867, 5.911791, 2.216145, 0.012467, -0.027603, 5.785357,
+ 2.216447, 0.018156, -0.040159, 5.901121, 2.215958, 0.024758, -0.054670, 5.908781, 2.215654,
+ 0.032395, -0.071352, 5.906098, 2.215283, 0.041108, -0.090201, 5.902558, 2.214715, 0.050955,
+ -0.111004, 5.895707, 2.213905, 0.061968, -0.134002, 5.888736, 2.212807, 0.074206, -0.159038,
+ 5.880633, 2.211303, 0.087742, -0.185801, 5.867001, 2.209297, 0.102652, -0.214368, 5.851446,
+ 2.206657, 0.119006, -0.244573, 5.830722, 2.203232, 0.136883, -0.276067, 5.802688, 2.198778,
+ 0.156335, -0.308660, 5.767185, 2.193091, 0.177396, -0.341940, 5.719726, 2.185858, 0.200070,
+ -0.375591, 5.658792, 2.176584, 0.224067, -0.408564, 5.573508, 2.164759, 0.249420, -0.440668,
+ 5.465696, 2.149777, 0.275879, -0.471138, 5.332207, 2.131225, 0.303307, -0.499204, 5.173339,
+ 2.108794, 0.331189, -0.524547, 4.985102, 2.080585, 0.359932, -0.547256, 4.785788, 2.047792,
+ 0.389063, -0.566479, 4.569344, 2.009518, 0.418725, -0.583031, 4.349557, 1.965601, 0.448181,
+ -0.595809, 4.121278, 1.916911, 0.477703, -0.605102, 3.892291, 1.863530, 0.507999, -0.612462,
+ 3.676557, 1.806286, 0.536889, -0.615451, 3.456241, 1.745841, 0.565778, -0.616029, 3.249464,
+ 1.681137, 0.593863, -0.613644, 3.050273, 1.615238, 0.620770, -0.608268, 2.859599, 1.548003,
+ 0.647171, -0.601116, 2.683287, 1.480447, 0.673458, -0.592840, 2.524036, 1.412084, 0.698064,
+ -0.581973, 2.371046, 1.345130, 0.721011, -0.568963, 2.229104, 1.278440, 0.744293, -0.555642,
+ 2.103213, 1.212448, 0.766314, -0.540934, 1.985370, 1.146287, 0.788164, -0.525271, 1.878842,
+ 1.082600, 0.809019, -0.507986, 1.779821, 1.019978, 0.830947, -0.489717, 1.691630, 0.956931,
+ 0.853732, -0.469345, 1.607513, 0.894207, 0.874904, -0.447618, 1.531176, 0.833436, 0.897289,
+ -0.426124, 1.467302, 0.773611, 0.919226, -0.404025, 1.408321, 0.716016, 0.940860, -0.381454,
+ 1.356209, 0.659515, 0.962764, -0.358901, 1.310082, 0.604629, 0.984322, -0.335983, 1.268485,
+ 0.552335, 1.005343, -0.312533, 1.230662, 0.501591, 1.028153, -0.289452, 1.199168, 0.452032,
+ 1.049283, -0.265754, 1.168575, 0.404347, 1.073687, -0.242571, 1.143533, 0.357445, 1.097546,
+ -0.218681, 1.119859, 0.312534, 1.123340, -0.194465, 1.099634, 0.269437, 1.148166, -0.168797,
+ 1.081968, 0.228586, 1.172518, -0.141552, 1.068789, 0.189866, 1.192930, -0.113325, 1.057548,
+ 0.152772, 1.206816, -0.084800, 1.044145, 0.115390, 1.215045, -0.056019, 1.028938, 0.076493,
+ 1.220048, -0.027733, 1.013338, 0.037767, 1.225852, 0.000050, 0.999927, -0.000160, 0.000178,
+ -0.000422, 4.587902, 2.372253, 0.000504, -0.001195, 6.624675, 2.372248, 0.002016, -0.004782,
+ 6.626884, 2.372187, 0.004531, -0.010746, 6.607379, 2.372318, 0.008081, -0.019161, 6.640102,
+ 2.372084, 0.012637, -0.029945, 6.653708, 2.372128, 0.018167, -0.042999, 6.623837, 2.371902,
+ 0.024769, -0.058516, 6.624484, 2.371595, 0.032421, -0.076370, 6.620877, 2.371120, 0.041164,
+ -0.096474, 6.615235, 2.370428, 0.051057, -0.118786, 6.607844, 2.369440, 0.062136, -0.143390,
+ 6.599216, 2.368075, 0.074490, -0.170034, 6.588018, 2.366218, 0.088179, -0.198717, 6.572526,
+ 2.363747, 0.103307, -0.229147, 6.551868, 2.360517, 0.119964, -0.261253, 6.526089, 2.356304,
+ 0.138173, -0.294703, 6.489593, 2.350797, 0.158072, -0.329261, 6.443573, 2.343783, 0.179592,
+ -0.364298, 6.379764, 2.334673, 0.202709, -0.399375, 6.295845, 2.323125, 0.227335, -0.433616,
+ 6.184929, 2.308547, 0.253230, -0.466794, 6.045905, 2.289980, 0.280100, -0.497509, 5.871803,
+ 2.266964, 0.308146, -0.525956, 5.672422, 2.239074, 0.336544, -0.551101, 5.443256, 2.204809,
+ 0.365223, -0.572471, 5.188034, 2.164827, 0.395484, -0.592088, 4.943783, 2.119489, 0.424416,
+ -0.606026, 4.666400, 2.067262, 0.455641, -0.619671, 4.418961, 2.009937, 0.485298, -0.627583,
+ 4.152737, 1.948900, 0.514774, -0.632072, 3.893344, 1.882692, 0.544172, -0.634033, 3.645332,
+ 1.814073, 0.573283, -0.633239, 3.414651, 1.742717, 0.602155, -0.630008, 3.195712, 1.669703,
+ 0.630520, -0.624550, 2.994536, 1.596021, 0.657121, -0.615749, 2.799373, 1.522572, 0.682071,
+ -0.604738, 2.616102, 1.448978, 0.707605, -0.593301, 2.456112, 1.376250, 0.731492, -0.579628,
+ 2.303517, 1.305297, 0.754139, -0.564473, 2.165340, 1.235548, 0.776505, -0.548787, 2.041646,
+ 1.167051, 0.796833, -0.531415, 1.923334, 1.100534, 0.817565, -0.513778, 1.818176, 1.035144,
+ 0.837981, -0.495167, 1.723830, 0.971583, 0.858513, -0.475690, 1.638448, 0.908841, 0.879892,
+ -0.454099, 1.559420, 0.846701, 0.902258, -0.432038, 1.491471, 0.785332, 0.924114, -0.409316,
+ 1.428878, 0.726409, 0.944230, -0.385618, 1.370785, 0.668588, 0.967001, -0.362604, 1.323529,
+ 0.612943, 0.988579, -0.339117, 1.279679, 0.559038, 1.010210, -0.315355, 1.240104, 0.506867,
+ 1.032084, -0.291408, 1.205261, 0.456934, 1.054671, -0.267387, 1.175197, 0.407792, 1.078314,
+ -0.243346, 1.148153, 0.360992, 1.102443, -0.219205, 1.123799, 0.315577, 1.128524, -0.194996,
+ 1.102624, 0.271742, 1.153989, -0.169897, 1.085134, 0.230702, 1.179420, -0.143960, 1.071699,
+ 0.192146, 1.200098, -0.116173, 1.060179, 0.155164, 1.214837, -0.086655, 1.046290, 0.117071,
+ 1.222749, -0.056956, 1.030040, 0.077450, 1.227273, -0.027883, 1.013650, 0.038092, 1.233293,
+ 0.000831, 1.000043, -0.000462, 0.000173, -0.000442, 4.741539, 2.547922, 0.000504, -0.001284,
+ 7.491127, 2.547919, 0.002014, -0.005132, 7.484889, 2.547844, 0.004523, -0.011521, 7.439875,
+ 2.547587, 0.008059, -0.020524, 7.483694, 2.547725, 0.012586, -0.032029, 7.470912, 2.547685,
+ 0.018081, -0.045948, 7.422534, 2.547686, 0.024783, -0.062844, 7.487581, 2.547107, 0.032451,
+ -0.082011, 7.483603, 2.546522, 0.041233, -0.103540, 7.475124, 2.545684, 0.051181, -0.127537,
+ 7.467521, 2.544438, 0.062347, -0.153921, 7.456266, 2.542744, 0.074829, -0.182427, 7.440422,
+ 2.540459, 0.088703, -0.213134, 7.420694, 2.537380, 0.104080, -0.245750, 7.394875, 2.533347,
+ 0.121050, -0.279941, 7.358515, 2.528069, 0.139697, -0.315591, 7.313001, 2.521237, 0.160036,
+ -0.351980, 7.246342, 2.512378, 0.182147, -0.388993, 7.163688, 2.500993, 0.205799, -0.425570,
+ 7.048339, 2.486450, 0.231091, -0.461093, 6.902586, 2.468174, 0.257405, -0.494668, 6.712721,
+ 2.444774, 0.284956, -0.525889, 6.491261, 2.415538, 0.313180, -0.553693, 6.232833, 2.380610,
+ 0.342327, -0.578724, 5.953834, 2.338525, 0.371689, -0.599706, 5.649698, 2.290256, 0.401919,
+ -0.617615, 5.347900, 2.235157, 0.432204, -0.631632, 5.036417, 2.173932, 0.463151, -0.643082,
+ 4.735976, 2.107298, 0.493388, -0.649970, 4.432044, 2.036121, 0.524128, -0.654188, 4.145472,
+ 1.961595, 0.553930, -0.654671, 3.866877, 1.883602, 0.583856, -0.653051, 3.607848, 1.804521,
+ 0.611762, -0.646994, 3.356237, 1.724047, 0.639117, -0.638860, 3.122531, 1.643016, 0.666279,
+ -0.629093, 2.913178, 1.563932, 0.692936, -0.617862, 2.722675, 1.484614, 0.716498, -0.603279,
+ 2.536926, 1.406734, 0.742273, -0.589878, 2.381054, 1.331469, 0.764031, -0.572744, 2.228312,
+ 1.256796, 0.786601, -0.555933, 2.095451, 1.185290, 0.807776, -0.537992, 1.972866, 1.115940,
+ 0.828400, -0.519596, 1.863394, 1.048371, 0.847412, -0.499847, 1.760630, 0.982934, 0.866850,
+ -0.479920, 1.670998, 0.919972, 0.886340, -0.459434, 1.587962, 0.858100, 0.906933, -0.437767,
+ 1.515505, 0.796714, 0.927490, -0.414068, 1.448243, 0.736162, 0.950217, -0.390910, 1.390505,
+ 0.677613, 0.971545, -0.366964, 1.337865, 0.620477, 0.992901, -0.342603, 1.291104, 0.565807,
+ 1.015460, -0.318596, 1.251138, 0.513086, 1.037859, -0.294242, 1.214291, 0.461573, 1.060535,
+ -0.269601, 1.182517, 0.411838, 1.086885, -0.245608, 1.155300, 0.363221, 1.111237, -0.220589,
+ 1.129715, 0.317174, 1.138718, -0.196008, 1.108103, 0.273213, 1.164223, -0.170408, 1.089640,
+ 0.231968, 1.187256, -0.144205, 1.074145, 0.192987, 1.207851, -0.116945, 1.061615, 0.156118,
+ 1.222217, -0.088852, 1.047599, 0.118674, 1.230315, -0.059381, 1.030869, 0.078993, 1.235052,
+ -0.029145, 1.014126, 0.038924, 1.241359, 0.000479, 1.000114, -0.000211, 0.000169, -0.000465,
+ 4.953966, 2.747437, 0.000504, -0.001384, 8.544530, 2.747430, 0.002015, -0.005537, 8.545147,
+ 2.747339, 0.004542, -0.012477, 8.557734, 2.747125, 0.008064, -0.022143, 8.530193, 2.747341,
+ 0.012543, -0.034411, 8.465151, 2.747411, 0.018178, -0.049792, 8.543328, 2.746874, 0.024810,
+ -0.067784, 8.547247, 2.746396, 0.032489, -0.088416, 8.537436, 2.745730, 0.041313, -0.111580,
+ 8.526655, 2.744596, 0.051332, -0.137462, 8.517438, 2.743082, 0.062603, -0.165860, 8.502803,
+ 2.740950, 0.075240, -0.196548, 8.481507, 2.738057, 0.089341, -0.229440, 8.454287, 2.734174,
+ 0.105021, -0.264395, 8.420289, 2.729086, 0.122399, -0.301020, 8.373503, 2.722420, 0.141526,
+ -0.338997, 8.309059, 2.713686, 0.162451, -0.377589, 8.221539, 2.702492, 0.185098, -0.416349,
+ 8.100116, 2.687893, 0.209406, -0.454284, 7.941704, 2.669386, 0.235098, -0.490450, 7.733318,
+ 2.645590, 0.262100, -0.524592, 7.486120, 2.615709, 0.290103, -0.555558, 7.193498, 2.579231,
+ 0.319135, -0.583516, 6.874796, 2.534957, 0.348286, -0.606714, 6.516118, 2.483017, 0.378840,
+ -0.627850, 6.163912, 2.424214, 0.409608, -0.644715, 5.801404, 2.357563, 0.440553, -0.657657,
+ 5.435955, 2.285835, 0.470599, -0.665621, 5.063481, 2.207940, 0.503172, -0.673767, 4.743532,
+ 2.126440, 0.533884, -0.676009, 4.413409, 2.040694, 0.563808, -0.674536, 4.092169, 1.953979,
+ 0.591849, -0.668913, 3.787057, 1.865897, 0.621474, -0.663159, 3.520578, 1.777762, 0.650500,
+ -0.655018, 3.275065, 1.689902, 0.678011, -0.643949, 3.043141, 1.603528, 0.703490, -0.630030,
+ 2.827104, 1.519484, 0.728250, -0.614910, 2.632620, 1.436677, 0.752165, -0.598649, 2.455570,
+ 1.355753, 0.775894, -0.581771, 2.295932, 1.278884, 0.797650, -0.563193, 2.152291, 1.202767,
+ 0.818505, -0.543750, 2.022099, 1.130338, 0.838596, -0.524017, 1.903562, 1.060263, 0.858396,
+ -0.504064, 1.797204, 0.993077, 0.877088, -0.483418, 1.701208, 0.928606, 0.896606, -0.462786,
+ 1.617736, 0.866039, 0.914342, -0.440943, 1.539227, 0.804293, 0.933550, -0.419129, 1.470383,
+ 0.745206, 0.955237, -0.396100, 1.409100, 0.685832, 0.976700, -0.371743, 1.354930, 0.627953,
+ 0.997681, -0.346882, 1.305249, 0.572127, 1.020784, -0.322391, 1.262603, 0.517941, 1.043840,
+ -0.297564, 1.225115, 0.466188, 1.067224, -0.272639, 1.190817, 0.415499, 1.092358, -0.247664,
+ 1.161265, 0.366782, 1.117573, -0.222260, 1.133935, 0.319377, 1.145730, -0.196933, 1.111750,
+ 0.275293, 1.170822, -0.170577, 1.091981, 0.233306, 1.194559, -0.143878, 1.075810, 0.193950,
+ 1.214819, -0.116347, 1.062438, 0.156724, 1.229830, -0.088233, 1.048092, 0.118984, 1.238185,
+ -0.059408, 1.031325, 0.079385, 1.243527, -0.030703, 1.014698, 0.039893, 1.249724, -0.001520,
+ 0.999819, 0.000760, 0.000164, -0.000489, 5.157359, 2.976300, 0.000505, -0.001502, 9.891415,
+ 2.976286, 0.002016, -0.006000, 9.857730, 2.976197, 0.004543, -0.013519, 9.870651, 2.975832,
+ 0.008064, -0.023985, 9.855780, 2.976170, 0.012611, -0.037471, 9.850209, 2.975941, 0.018162,
+ -0.053866, 9.827134, 2.974968, 0.024820, -0.073390, 9.849955, 2.975010, 0.032545, -0.095758,
+ 9.842021, 2.974073, 0.041418, -0.120834, 9.829989, 2.972700, 0.051511, -0.148861, 9.817421,
+ 2.970736, 0.062920, -0.179456, 9.797347, 2.968033, 0.075744, -0.212674, 9.771533, 2.964371,
+ 0.090131, -0.248193, 9.735924, 2.959437, 0.106187, -0.285748, 9.687707, 2.952881, 0.124035,
+ -0.325017, 9.622684, 2.944273, 0.143733, -0.365463, 9.531452, 2.933093, 0.165262, -0.406157,
+ 9.401732, 2.918484, 0.188622, -0.446833, 9.232451, 2.899529, 0.213693, -0.486209, 9.013432,
+ 2.875137, 0.239987, -0.522925, 8.725671, 2.844166, 0.267796, -0.557452, 8.400028, 2.805649,
+ 0.296547, -0.588266, 8.023041, 2.758720, 0.325838, -0.614837, 7.606773, 2.702676, 0.355479,
+ -0.636760, 7.160680, 2.638483, 0.386984, -0.657230, 6.736765, 2.566849, 0.418853, -0.673592,
+ 6.313742, 2.488091, 0.450302, -0.684966, 5.884479, 2.402458, 0.481149, -0.691591, 5.455771,
+ 2.311816, 0.512177, -0.695337, 5.055698, 2.217330, 0.543437, -0.696370, 4.681506, 2.121285,
+ 0.574309, -0.694186, 4.334716, 2.024160, 0.604787, -0.689158, 4.008524, 1.927738, 0.633483,
+ -0.680580, 3.703505, 1.830456, 0.660766, -0.669088, 3.418386, 1.734934, 0.688471, -0.656673,
+ 3.168101, 1.642316, 0.715729, -0.642820, 2.941735, 1.550744, 0.740435, -0.626155, 2.730570,
+ 1.463345, 0.764114, -0.608299, 2.537561, 1.378151, 0.787028, -0.589519, 2.364323, 1.297630,
+ 0.807985, -0.569257, 2.207970, 1.217830, 0.830663, -0.550055, 2.076646, 1.142746, 0.850416,
+ -0.528812, 1.948085, 1.070757, 0.869609, -0.507478, 1.834684, 1.001282, 0.888324, -0.486131,
+ 1.734879, 0.934987, 0.907482, -0.464910, 1.645974, 0.871203, 0.924829, -0.442742, 1.563550,
+ 0.809260, 0.942958, -0.420777, 1.491264, 0.750037, 0.961999, -0.398842, 1.428069, 0.691715,
+ 0.981043, -0.375967, 1.369668, 0.635669, 1.002371, -0.351469, 1.318588, 0.578689, 1.025343,
+ -0.326601, 1.273628, 0.524424, 1.048511, -0.301395, 1.234572, 0.471403, 1.072242, -0.275835,
+ 1.198354, 0.419950, 1.096758, -0.250200, 1.166392, 0.370733, 1.122781, -0.224474, 1.138991,
+ 0.322864, 1.150871, -0.198592, 1.114313, 0.277723, 1.177319, -0.171805, 1.093534, 0.234950,
+ 1.201765, -0.144291, 1.077462, 0.195376, 1.222629, -0.115949, 1.063288, 0.157315, 1.237334,
+ -0.087140, 1.048366, 0.118843, 1.246153, -0.058094, 1.031224, 0.079207, 1.252570, -0.029194,
+ 1.014695, 0.039376, 1.259060, -0.000418, 0.999881, 0.000307, 0.000159, -0.000515, 5.393984,
+ 3.241865, 0.000505, -0.001636, 11.548038, 3.241848, 0.002016, -0.006534, 11.506640, 3.241718,
+ 0.004537, -0.014706, 11.513460, 3.241196, 0.008068, -0.026134, 11.510533, 3.241693, 0.012573,
+ -0.040676, 11.428978, 3.241030, 0.018212, -0.058794, 11.510745, 3.240924, 0.024847, -0.079926,
+ 11.497339, 3.240201, 0.032603, -0.104160, 11.484607, 3.238994, 0.041543, -0.131552, 11.470801,
+ 3.237182, 0.051738, -0.162012, 11.453219, 3.234635, 0.063313, -0.195260, 11.427244, 3.231153,
+ 0.076381, -0.231205, 11.388534, 3.226361, 0.091096, -0.269678, 11.340406, 3.219943, 0.107600,
+ -0.310170, 11.270127, 3.211448, 0.126017, -0.352435, 11.178583, 3.200168, 0.146411, -0.395551,
+ 11.046559, 3.185328, 0.168663, -0.438627, 10.858624, 3.165972, 0.192730, -0.480660, 10.606379,
+ 3.140735, 0.218497, -0.520987, 10.288093, 3.108388, 0.245752, -0.558483, 9.907480, 3.067586,
+ 0.273993, -0.592090, 9.453246, 3.016931, 0.303495, -0.622416, 8.966138, 2.956444, 0.333717,
+ -0.648303, 8.443776, 2.885116, 0.363928, -0.668640, 7.894122, 2.805963, 0.396240, -0.687748,
+ 7.385728, 2.718338, 0.427161, -0.699903, 6.838511, 2.622346, 0.460175, -0.711210, 6.356371,
+ 2.522476, 0.492593, -0.717734, 5.878312, 2.417984, 0.524449, -0.719956, 5.423285, 2.310941,
+ 0.556010, -0.719127, 4.997909, 2.201885, 0.587032, -0.715077, 4.600426, 2.093330, 0.617030,
+ -0.707574, 4.235885, 1.986585, 0.644684, -0.695781, 3.881712, 1.881279, 0.674483, -0.685313,
+ 3.590960, 1.777918, 0.700290, -0.669619, 3.303138, 1.678004, 0.727892, -0.654728, 3.057771,
+ 1.581162, 0.751694, -0.635727, 2.826642, 1.487769, 0.776271, -0.617343, 2.622178, 1.399628,
+ 0.799502, -0.597683, 2.441265, 1.313195, 0.821768, -0.577090, 2.276954, 1.232316, 0.841960,
+ -0.555165, 2.125744, 1.153914, 0.861582, -0.532983, 1.991236, 1.079598, 0.881460, -0.510933,
+ 1.874027, 1.008883, 0.899952, -0.488321, 1.766812, 0.940802, 0.918954, -0.466405, 1.673436,
+ 0.875653, 0.936130, -0.443623, 1.586986, 0.813130, 0.954799, -0.421532, 1.513558, 0.752241,
+ 0.972435, -0.398897, 1.445787, 0.694711, 0.990147, -0.376302, 1.384382, 0.638770, 1.009189,
+ -0.353623, 1.331934, 0.583826, 1.029687, -0.330635, 1.284478, 0.530476, 1.052604, -0.305698,
+ 1.243632, 0.477187, 1.076524, -0.279917, 1.204997, 0.425349, 1.101701, -0.253951, 1.171750,
+ 0.375165, 1.127264, -0.227541, 1.142519, 0.326869, 1.156397, -0.201265, 1.116817, 0.280912,
+ 1.183020, -0.173943, 1.095289, 0.237447, 1.208448, -0.145860, 1.078296, 0.196694, 1.230417,
+ -0.116901, 1.064416, 0.158409, 1.248617, -0.087507, 1.050504, 0.119483, 1.257310, -0.057353,
+ 1.032796, 0.079092, 1.263076, -0.027785, 1.015128, 0.038883, 1.269870, 0.001331, 0.999935,
+ -0.000557, 0.000154, -0.000549, 5.705205, 3.554136, 0.000506, -0.001797, 13.703335, 3.554133,
+ 0.002014, -0.007156, 13.614074, 3.553937, 0.004544, -0.016145, 13.657344, 3.553096, 0.008070,
+ -0.028652, 13.627997, 3.553894, 0.012584, -0.044617, 13.606235, 3.554000, 0.018180, -0.064288,
+ 13.581339, 3.549637, 0.024887, -0.087627, 13.608851, 3.552006, 0.032690, -0.114134, 13.599099,
+ 3.550341, 0.041705, -0.144154, 13.579829, 3.547982, 0.052035, -0.177400, 13.552845, 3.544641,
+ 0.063810, -0.213813, 13.515619, 3.539941, 0.077171, -0.252978, 13.460460, 3.533696, 0.092329,
+ -0.294852, 13.393559, 3.524977, 0.109390, -0.338688, 13.292376, 3.513655, 0.128455, -0.384018,
+ 13.147332, 3.498484, 0.149661, -0.429960, 12.945774, 3.478323, 0.172694, -0.475024, 12.658979,
+ 3.451862, 0.197650, -0.518614, 12.289564, 3.417602, 0.224156, -0.559298, 11.828307, 3.372913,
+ 0.252008, -0.596110, 11.285162, 3.317454, 0.281165, -0.629292, 10.684922, 3.251171, 0.311434,
+ -0.658379, 10.052939, 3.172222, 0.342741, -0.683455, 9.405296, 3.082825, 0.373543, -0.701674,
+ 8.716078, 2.983976, 0.407008, -0.719664, 8.108425, 2.876244, 0.438623, -0.729882, 7.461252,
+ 2.763279, 0.471872, -0.738696, 6.880182, 2.645590, 0.504700, -0.743136, 6.324308, 2.524680,
+ 0.537118, -0.743676, 5.808302, 2.402723, 0.569412, -0.741181, 5.332306, 2.281437, 0.598202,
+ -0.732348, 4.857402, 2.161401, 0.629640, -0.724832, 4.465554, 2.043872, 0.659239, -0.713435,
+ 4.093661, 1.930129, 0.686547, -0.698539, 3.752593, 1.817654, 0.715529, -0.684471, 3.457593,
+ 1.712567, 0.739456, -0.664983, 3.171220, 1.610687, 0.764892, -0.646322, 2.929674, 1.512031,
+ 0.789301, -0.626393, 2.710719, 1.419033, 0.809881, -0.603498, 2.506139, 1.330115, 0.833385,
+ -0.582934, 2.336089, 1.245859, 0.854254, -0.560419, 2.178470, 1.165042, 0.873964, -0.537294,
+ 2.040087, 1.086633, 0.893433, -0.514264, 1.911969, 1.015028, 0.911756, -0.490657, 1.799840,
+ 0.944938, 0.930894, -0.467601, 1.703188, 0.878743, 0.948078, -0.444043, 1.612092, 0.815356,
+ 0.966162, -0.421155, 1.534444, 0.753883, 0.984166, -0.398238, 1.462397, 0.695534, 1.002184,
+ -0.375278, 1.400793, 0.638806, 1.019669, -0.352159, 1.344172, 0.584549, 1.039571, -0.329651,
+ 1.295227, 0.531660, 1.059989, -0.306804, 1.251281, 0.480529, 1.081116, -0.283345, 1.211504,
+ 0.430071, 1.105742, -0.258568, 1.176400, 0.380277, 1.133080, -0.232146, 1.144519, 0.331076,
+ 1.161888, -0.205244, 1.118059, 0.284040, 1.192408, -0.177932, 1.097561, 0.239958, 1.221043,
+ -0.149532, 1.082021, 0.198751, 1.244141, -0.120046, 1.067634, 0.160114, 1.259465, -0.089542,
+ 1.051626, 0.121101, 1.268124, -0.058593, 1.033296, 0.079898, 1.274330, -0.028011, 1.015382,
+ 0.039038, 1.281590, 0.002330, 1.000087, -0.001259, 0.000149, -0.000587, 6.059834, 3.927143,
+ 0.000507, -0.001992, 16.560400, 3.927149, 0.002014, -0.007910, 16.406326, 3.926821, 0.004549,
+ -0.017856, 16.545532, 3.927027, 0.008064, -0.031632, 16.375853, 3.925487, 0.012450, -0.048749,
+ 15.928564, 3.928272, 0.018030, -0.070371, 16.072989, 3.917862, 0.024964, -0.096897, 16.458925,
+ 3.924489, 0.032807, -0.126073, 16.377851, 3.921896, 0.041917, -0.159205, 16.351561, 3.918860,
+ 0.052416, -0.195762, 16.307037, 3.914339, 0.064464, -0.235784, 16.255514, 3.907954, 0.078225,
+ -0.278812, 16.176226, 3.899254, 0.093900, -0.324457, 16.066530, 3.887455, 0.111657, -0.372174,
+ 15.913818, 3.871777, 0.131478, -0.420530, 15.669197, 3.850776, 0.153574, -0.469330, 15.355453,
+ 3.822348, 0.177505, -0.516029, 14.908978, 3.785168, 0.203383, -0.560585, 14.352687, 3.736602,
+ 0.230569, -0.600607, 13.666022, 3.675046, 0.259188, -0.636296, 12.900244, 3.599811, 0.289272,
+ -0.668312, 12.111226, 3.510550, 0.320490, -0.695986, 11.292102, 3.408535, 0.353031, -0.719848,
+ 10.493485, 3.295667, 0.385228, -0.737073, 9.661955, 3.171998, 0.419219, -0.752419, 8.909942,
+ 3.042428, 0.452096, -0.761179, 8.155107, 2.907108, 0.484909, -0.766166, 7.450609, 2.769858,
+ 0.518306, -0.768596, 6.811866, 2.631935, 0.550067, -0.765683, 6.205275, 2.492870, 0.582562,
+ -0.761197, 5.663215, 2.358645, 0.614450, -0.753834, 5.165358, 2.227377, 0.644563, -0.742860,
+ 4.712554, 2.097547, 0.673658, -0.729294, 4.306101, 1.974920, 0.702857, -0.714839, 3.943352,
+ 1.857613, 0.729350, -0.696774, 3.609432, 1.743601, 0.754958, -0.677394, 3.308389, 1.636607,
+ 0.779575, -0.657018, 3.043803, 1.533841, 0.800491, -0.633342, 2.793592, 1.437092, 0.825030,
+ -0.612471, 2.590307, 1.344272, 0.847535, -0.589882, 2.406477, 1.256436, 0.865979, -0.564850,
+ 2.231999, 1.173938, 0.886254, -0.541357, 2.083556, 1.094722, 0.905566, -0.517353, 1.950928,
+ 1.021107, 0.924607, -0.493320, 1.835979, 0.948941, 0.943365, -0.469366, 1.731417, 0.881060,
+ 0.960405, -0.444745, 1.635838, 0.816479, 0.977893, -0.420493, 1.552981, 0.754604, 0.996573,
+ -0.397150, 1.481595, 0.694917, 1.014000, -0.373483, 1.414070, 0.638445, 1.031807, -0.349985,
+ 1.356031, 0.584035, 1.051877, -0.327062, 1.305041, 0.530010, 1.071701, -0.304134, 1.258836,
+ 0.479439, 1.093109, -0.280962, 1.217297, 0.429763, 1.116681, -0.258121, 1.182063, 0.381050,
+ 1.143886, -0.235365, 1.150039, 0.333395, 1.175163, -0.211621, 1.125074, 0.287477, 1.203675,
+ -0.184061, 1.102339, 0.243301, 1.230477, -0.154815, 1.083927, 0.201826, 1.253134, -0.124513,
+ 1.067989, 0.162271, 1.270092, -0.093383, 1.052032, 0.122855, 1.279576, -0.061770, 1.033685,
+ 0.081639, 1.286472, -0.030317, 1.015583, 0.040411, 1.294476, 0.000964, 1.000206, -0.000454,
+ 0.000144, -0.000630, 6.467978, 4.381146, 0.000504, -0.002208, 20.193617, 4.381151, 0.002017,
+ -0.008834, 20.206446, 4.380687, 0.004536, -0.019864, 20.183254, 4.380550, 0.008174, -0.035759,
+ 20.564249, 4.381247, 0.012608, -0.055034, 20.111612, 4.382390, 0.018198, -0.079119, 20.106096,
+ 4.379815, 0.025057, -0.108067, 20.215635, 4.376874, 0.032962, -0.140630, 20.153549, 4.374143,
+ 0.042199, -0.177350, 20.084061, 4.369558, 0.052928, -0.218094, 20.026609, 4.363287, 0.065327,
+ -0.262407, 19.940054, 4.354386, 0.079568, -0.309833, 19.806814, 4.342127, 0.095961, -0.360074,
+ 19.641878, 4.325533, 0.114516, -0.411747, 19.370914, 4.302950, 0.135349, -0.463726, 18.983900,
+ 4.271991, 0.158293, -0.514211, 18.433926, 4.230856, 0.183348, -0.562511, 17.733471, 4.176250,
+ 0.209959, -0.606310, 16.864214, 4.105895, 0.238736, -0.646958, 15.935207, 4.020104, 0.268543,
+ -0.681574, 14.890014, 3.916094, 0.299996, -0.712458, 13.846786, 3.798239, 0.331930, -0.737130,
+ 12.758296, 3.664191, 0.365222, -0.758156, 11.732940, 3.521867, 0.399061, -0.774364, 10.741743,
+ 3.369831, 0.433480, -0.786412, 9.812527, 3.212079, 0.467002, -0.792373, 8.915130, 3.053715,
+ 0.500754, -0.795410, 8.094276, 2.894526, 0.534023, -0.794617, 7.342067, 2.735959, 0.566988,
+ -0.790689, 6.664186, 2.581160, 0.599960, -0.784433, 6.052983, 2.432318, 0.630599, -0.773378,
+ 5.486277, 2.287630, 0.660807, -0.760334, 4.982516, 2.150183, 0.690103, -0.745430, 4.531104,
+ 2.017266, 0.717315, -0.727511, 4.120734, 1.891699, 0.743819, -0.708376, 3.759599, 1.772680,
+ 0.770147, -0.688632, 3.441912, 1.660620, 0.793510, -0.665931, 3.152600, 1.553166, 0.816535,
+ -0.643045, 2.898883, 1.452080, 0.839163, -0.619917, 2.674488, 1.355544, 0.859066, -0.594923,
+ 2.469262, 1.267232, 0.879489, -0.570343, 2.292209, 1.181702, 0.898525, -0.544975, 2.131086,
+ 1.102089, 0.918359, -0.520585, 1.994526, 1.024744, 0.937502, -0.496044, 1.873079, 0.951712,
+ 0.955573, -0.471010, 1.761232, 0.883374, 0.972957, -0.445712, 1.661604, 0.818008, 0.991248,
+ -0.421201, 1.577169, 0.754446, 1.008997, -0.396444, 1.499653, 0.694518, 1.028127, -0.372362,
+ 1.432030, 0.637259, 1.045710, -0.347895, 1.369870, 0.581515, 1.065977, -0.324409, 1.317341,
+ 0.527713, 1.087469, -0.301181, 1.270447, 0.476281, 1.109943, -0.277866, 1.228398, 0.426403,
+ 1.134440, -0.254849, 1.190986, 0.377822, 1.160986, -0.231754, 1.157681, 0.330740, 1.188458,
+ -0.207973, 1.128665, 0.286014, 1.214405, -0.183424, 1.103711, 0.243600, 1.239504, -0.157972,
+ 1.084253, 0.203686, 1.262961, -0.130607, 1.068258, 0.165214, 1.280340, -0.099652, 1.051919,
+ 0.126067, 1.292129, -0.067363, 1.034016, 0.084791, 1.299876, -0.035026, 1.015775, 0.042786,
+ 1.308328, -0.002944, 0.999963, 0.001385, 0.000138, -0.000681, 6.943771, 4.946556, 0.000503,
+ -0.002486, 25.346689, 4.946532, 0.002016, -0.009973, 25.494320, 4.946311, 0.004539, -0.022440,
+ 25.484949, 4.945823, 0.008069, -0.039836, 25.420902, 4.945311, 0.012628, -0.062172, 25.394403,
+ 4.945041, 0.018294, -0.089609, 25.440279, 4.943295, 0.025079, -0.121584, 25.399988, 4.939368,
+ 0.033142, -0.158595, 25.356537, 4.936200, 0.042596, -0.199971, 25.295067, 4.929842, 0.053628,
+ -0.245624, 25.196465, 4.920586, 0.066496, -0.295240, 25.055311, 4.907700, 0.081434, -0.348006,
+ 24.846170, 4.889647, 0.098640, -0.403167, 24.527803, 4.864680, 0.118231, -0.459106, 24.051735,
+ 4.830574, 0.140139, -0.513907, 23.352467, 4.783530, 0.164198, -0.565953, 22.418245, 4.720530,
+ 0.190502, -0.614858, 21.324049, 4.638075, 0.218530, -0.658304, 20.038671, 4.535464, 0.248094,
+ -0.696133, 18.639786, 4.411646, 0.279435, -0.729388, 17.234526, 4.268872, 0.312002, -0.757534,
+ 15.830426, 4.109603, 0.346173, -0.781866, 14.495901, 3.938782, 0.379435, -0.797579, 13.136444,
+ 3.756138, 0.414945, -0.812334, 11.946491, 3.571258, 0.449991, -0.821119, 10.811908, 3.384217,
+ 0.484636, -0.825066, 9.763482, 3.198076, 0.518675, -0.824728, 8.796811, 3.015808, 0.552559,
+ -0.821710, 7.932528, 2.836886, 0.587272, -0.817478, 7.185156, 2.664995, 0.616960, -0.804441,
+ 6.445302, 2.502223, 0.648054, -0.792063, 5.818812, 2.345851, 0.678575, -0.777793, 5.264731,
+ 2.197150, 0.707287, -0.760476, 4.766033, 2.056042, 0.735851, -0.742541, 4.335871, 1.922805,
+ 0.760594, -0.720503, 3.928021, 1.798585, 0.784534, -0.697719, 3.579153, 1.680605, 0.811029,
+ -0.677036, 3.285307, 1.568942, 0.831809, -0.651479, 3.001423, 1.465496, 0.854364, -0.627376,
+ 2.760672, 1.367849, 0.872639, -0.600496, 2.540697, 1.275644, 0.894296, -0.576297, 2.355273,
+ 1.188638, 0.913123, -0.550377, 2.188563, 1.105652, 0.932025, -0.524640, 2.040739, 1.028614,
+ 0.949876, -0.498402, 1.910315, 0.954421, 0.968933, -0.473220, 1.795750, 0.884061, 0.985366,
+ -0.447086, 1.690336, 0.817765, 1.004940, -0.422394, 1.599626, 0.753295, 1.022217, -0.396726,
+ 1.519055, 0.693380, 1.041490, -0.371854, 1.448745, 0.635747, 1.059920, -0.346769, 1.384292,
+ 0.579508, 1.080408, -0.322343, 1.328798, 0.525045, 1.101632, -0.297979, 1.279898, 0.473773,
+ 1.124812, -0.274059, 1.234005, 0.422949, 1.148503, -0.249954, 1.195373, 0.374609, 1.174554,
+ -0.225988, 1.160362, 0.327350, 1.202931, -0.201932, 1.131307, 0.283494, 1.229335, -0.176886,
+ 1.105885, 0.241092, 1.254254, -0.151225, 1.085802, 0.201514, 1.275743, -0.124282, 1.068524,
+ 0.162866, 1.292929, -0.097122, 1.051493, 0.124991, 1.305805, -0.068939, 1.033890, 0.085521,
+ 1.314991, -0.040082, 1.015927, 0.045247, 1.324033, -0.009923, 0.999893, 0.004738, 0.000131,
+ -0.000745, 7.562414, 5.671075, 0.000473, -0.002681, 27.216688, 5.670949, 0.002021, -0.011462,
+ 32.962402, 5.670177, 0.004540, -0.025728, 33.183949, 5.670197, 0.008087, -0.045746, 33.185688,
+ 5.667313, 0.012673, -0.071427, 33.170441, 5.668396, 0.018358, -0.102673, 33.145138, 5.665252,
+ 0.025299, -0.139780, 33.303326, 5.653404, 0.033469, -0.181718, 33.107243, 5.652829, 0.043139,
+ -0.228698, 32.859524, 5.645676, 0.054622, -0.280648, 32.694893, 5.631547, 0.068115, -0.336524,
+ 32.422569, 5.611561, 0.083957, -0.395671, 32.035511, 5.583449, 0.102259, -0.456164, 31.415047,
+ 5.543651, 0.123021, -0.515765, 30.470440, 5.488278, 0.146127, -0.572309, 29.186451, 5.413118,
+ 0.171749, -0.625710, 27.653852, 5.312369, 0.199549, -0.673853, 25.902435, 5.185774, 0.229188,
+ -0.715905, 23.978609, 5.030582, 0.260421, -0.751533, 21.999035, 4.853484, 0.293421, -0.782309,
+ 20.087366, 4.656137, 0.327077, -0.806332, 18.186535, 4.443975, 0.361892, -0.825818, 16.418409,
+ 4.223844, 0.397146, -0.840019, 14.774344, 3.998959, 0.434169, -0.852434, 13.321097, 3.775443,
+ 0.469288, -0.856632, 11.929448, 3.552818, 0.504319, -0.857130, 10.675201, 3.338825, 0.540067,
+ -0.855903, 9.591900, 3.130547, 0.575404, -0.851565, 8.607655, 2.932930, 0.606782, -0.839818,
+ 7.690560, 2.743876, 0.638660, -0.827508, 6.900781, 2.565115, 0.670577, -0.814154, 6.216821,
+ 2.395215, 0.696718, -0.793162, 5.551886, 2.238233, 0.725990, -0.775291, 5.015406, 2.090264,
+ 0.754140, -0.755758, 4.546843, 1.950834, 0.775992, -0.729824, 4.094254, 1.820582, 0.802990,
+ -0.708909, 3.732984, 1.699191, 0.828291, -0.686483, 3.413194, 1.583805, 0.847406, -0.659162,
+ 3.103861, 1.478093, 0.864951, -0.631051, 2.832976, 1.378496, 0.887154, -0.606590, 2.616645,
+ 1.282127, 0.906337, -0.580124, 2.413988, 1.194643, 0.927184, -0.554835, 2.244380, 1.110354,
+ 0.943810, -0.527583, 2.081964, 1.031996, 0.963630, -0.502243, 1.948979, 0.956718, 0.979691,
+ -0.475006, 1.822701, 0.886957, 0.997690, -0.448815, 1.715714, 0.819006, 1.016460, -0.423044,
+ 1.621868, 0.754892, 1.035485, -0.397637, 1.539537, 0.693707, 1.053165, -0.371775, 1.462285,
+ 0.634867, 1.072394, -0.346372, 1.396193, 0.578574, 1.093397, -0.321291, 1.338344, 0.524341,
+ 1.115194, -0.296102, 1.287594, 0.472059, 1.137943, -0.271023, 1.240495, 0.421674, 1.164163,
+ -0.246367, 1.201224, 0.371963, 1.191457, -0.221414, 1.164472, 0.325040, 1.220253, -0.196228,
+ 1.134325, 0.280343, 1.245456, -0.169991, 1.108214, 0.238098, 1.270647, -0.143314, 1.087277,
+ 0.197886, 1.292124, -0.115881, 1.069397, 0.159560, 1.309091, -0.087816, 1.051426, 0.120547,
+ 1.321130, -0.059301, 1.032904, 0.080834, 1.332484, -0.030912, 1.015767, 0.040933, 1.342834,
+ -0.002172, 0.999591, 0.001185, 0.000125, -0.000830, 8.392562, 6.634228, 0.000443, -0.002936,
+ 29.687805, 6.634032, 0.002016, -0.013374, 45.025234, 6.633008, 0.004540, -0.030089, 45.020294,
+ 6.633056, 0.008092, -0.053499, 45.066029, 6.626466, 0.012710, -0.083610, 44.810101, 6.630330,
+ 0.018485, -0.120260, 45.216747, 6.614516, 0.025134, -0.161031, 44.674168, 6.600349, 0.033897,
+ -0.212161, 44.819195, 6.610186, 0.043978, -0.266661, 44.450245, 6.593605, 0.056094, -0.326582,
+ 44.134544, 6.570142, 0.070528, -0.390342, 43.591648, 6.536712, 0.087498, -0.456162, 42.708160,
+ 6.488329, 0.107138, -0.521609, 41.365093, 6.420198, 0.129461, -0.584225, 39.525822, 6.323702,
+ 0.154245, -0.641931, 37.186111, 6.193606, 0.181228, -0.692829, 34.478470, 6.026897, 0.210711,
+ -0.738440, 31.680904, 5.825769, 0.242181, -0.777397, 28.828054, 5.595428, 0.275337, -0.809980,
+ 26.042755, 5.342321, 0.309698, -0.835990, 23.376804, 5.073076, 0.345702, -0.858077, 20.965754,
+ 4.794572, 0.382135, -0.874122, 18.710079, 4.516676, 0.419871, -0.887133, 16.713011, 4.241767,
+ 0.455609, -0.891199, 14.819674, 3.972124, 0.492617, -0.894082, 13.187921, 3.717271, 0.528186,
+ -0.891270, 11.708584, 3.471719, 0.563462, -0.885719, 10.422834, 3.237760, 0.596013, -0.874241,
+ 9.237741, 3.019060, 0.629455, -0.862814, 8.248549, 2.813572, 0.661110, -0.848126, 7.358398,
+ 2.621046, 0.690314, -0.829798, 6.569392, 2.441627, 0.720589, -0.812314, 5.905934, 2.274629,
+ 0.745631, -0.788704, 5.276800, 2.119423, 0.771488, -0.766133, 4.752773, 1.974380, 0.798704,
+ -0.744726, 4.306095, 1.839482, 0.820172, -0.718062, 3.889792, 1.713244, 0.844368, -0.693972,
+ 3.545456, 1.594809, 0.863128, -0.665748, 3.212762, 1.487512, 0.880094, -0.637003, 2.926572,
+ 1.386724, 0.904252, -0.613728, 2.704260, 1.288131, 0.920506, -0.585217, 2.483164, 1.199845,
+ 0.940919, -0.559603, 2.300348, 1.114958, 0.957044, -0.531597, 2.130516, 1.034754, 0.972648,
+ -0.503583, 1.979313, 0.960912, 0.994318, -0.478813, 1.859664, 0.889786, 1.008754, -0.450943,
+ 1.742705, 0.820833, 1.028667, -0.425516, 1.645220, 0.756332, 1.046145, -0.398977, 1.557184,
+ 0.693921, 1.067212, -0.373657, 1.480814, 0.635955, 1.084111, -0.346657, 1.408762, 0.578832,
+ 1.106749, -0.321392, 1.350468, 0.523561, 1.128440, -0.295773, 1.294865, 0.471146, 1.151073,
+ -0.270028, 1.246118, 0.420298, 1.178601, -0.244816, 1.204226, 0.370575, 1.206845, -0.219027,
+ 1.166896, 0.323716, 1.235963, -0.192622, 1.135756, 0.278058, 1.263030, -0.165331, 1.109240,
+ 0.235743, 1.288937, -0.137489, 1.088379, 0.195390, 1.310681, -0.108685, 1.068987, 0.156439,
+ 1.334352, -0.079710, 1.054273, 0.117096, 1.344847, -0.049947, 1.034598, 0.076554, 1.354943,
+ -0.020272, 1.016079, 0.035585, 1.365515, 0.009170, 0.999969, -0.004771, 0.000117, -0.000935,
+ 9.424866, 7.979243, 0.000410, -0.003275, 33.013195, 7.979422, 0.002009, -0.016024, 64.370331,
+ 7.977156, 0.004541, -0.036176, 64.655952, 7.976128, 0.008109, -0.064384, 64.864494, 7.964988,
+ 0.012694, -0.099984, 64.487198, 7.971348, 0.018554, -0.143991, 64.637970, 7.923116, 0.025303,
+ -0.192040, 61.930538, 7.953975, 0.035297, -0.259442, 66.274422, 7.921861, 0.045226, -0.318370,
+ 63.334690, 7.909609, 0.058370, -0.388821, 62.686401, 7.864696, 0.074083, -0.461667, 61.332054,
+ 7.801843, 0.092537, -0.533744, 59.125607, 7.708949, 0.113781, -0.601905, 55.997845, 7.575799,
+ 0.137786, -0.664409, 52.177567, 7.393524, 0.164770, -0.721193, 48.019485, 7.161756, 0.193894,
+ -0.768842, 43.460278, 6.882018, 0.225586, -0.810332, 39.086590, 6.564607, 0.259311, -0.845096,
+ 34.896049, 6.221983, 0.294517, -0.872849, 30.952213, 5.865831, 0.331163, -0.895159, 27.375792,
+ 5.507064, 0.368964, -0.912860, 24.213310, 5.149763, 0.407255, -0.925338, 21.364958, 4.806172,
+ 0.444704, -0.930956, 18.791691, 4.472272, 0.482041, -0.932576, 16.521160, 4.160864, 0.519572,
+ -0.931547, 14.589918, 3.865206, 0.556236, -0.926554, 12.887797, 3.590445, 0.590431, -0.915839,
+ 11.352402, 3.332747, 0.622723, -0.901266, 10.002660, 3.093264, 0.657029, -0.888747, 8.905210,
+ 2.873842, 0.686164, -0.868666, 7.876704, 2.666740, 0.719168, -0.853152, 7.051816, 2.479017,
+ 0.742294, -0.826169, 6.226034, 2.306498, 0.770320, -0.804936, 5.590831, 2.141328, 0.792337,
+ -0.777772, 4.984083, 1.994663, 0.819050, -0.755478, 4.507655, 1.853950, 0.837684, -0.726072,
+ 4.049884, 1.725590, 0.861324, -0.701424, 3.678201, 1.606303, 0.880741, -0.673615, 3.337163,
+ 1.495452, 0.903335, -0.648506, 3.055720, 1.391162, 0.920311, -0.619640, 2.792068, 1.294734,
+ 0.935769, -0.590245, 2.554566, 1.204518, 0.956592, -0.564944, 2.366468, 1.118630, 0.972424,
+ -0.536842, 2.187863, 1.038323, 0.986269, -0.508020, 2.023480, 0.963803, 1.006122, -0.482411,
+ 1.895137, 0.890986, 1.022504, -0.455110, 1.775886, 0.820936, 1.037905, -0.427450, 1.665951,
+ 0.758556, 1.059281, -0.402198, 1.577363, 0.696126, 1.076613, -0.375156, 1.493391, 0.636676,
+ 1.097828, -0.349577, 1.421129, 0.579947, 1.116671, -0.322955, 1.355205, 0.525140, 1.140514,
+ -0.297406, 1.299979, 0.471460, 1.166473, -0.271786, 1.249847, 0.420473, 1.192591, -0.245461,
+ 1.204625, 0.371118, 1.223349, -0.219412, 1.166686, 0.322600, 1.254833, -0.192660, 1.134121,
+ 0.277572, 1.285808, -0.165167, 1.108617, 0.234417, 1.322015, -0.137236, 1.093841, 0.194640,
+ 1.342172, -0.106871, 1.074616, 0.155001, 1.357238, -0.075759, 1.053550, 0.114648, 1.367725,
+ -0.044279, 1.033851, 0.073254, 1.379461, -0.013001, 1.015713, 0.031895, 1.391625, 0.018075,
+ 1.000203, -0.009397, 0.000109, -0.001093, 10.986820, 9.992467, 0.000378, -0.003779, 37.989063,
+ 9.992861, 0.002028, -0.020252, 101.850441, 9.988345, 0.004557, -0.045429, 101.106750, 9.983879,
+ 0.008115, -0.080453, 100.646606, 9.953411, 0.012864, -0.125836, 101.366592, 9.943727, 0.018734,
+ -0.179350, 100.786118, 9.908408, 0.026314, -0.243680, 99.779343, 9.821631, 0.035500, -0.313552,
+ 98.608231, 9.782450, 0.047562, -0.394644, 97.689568, 9.845875, 0.062065, -0.476697, 95.177795,
+ 9.755218, 0.079552, -0.557933, 91.095581, 9.615121, 0.099905, -0.632818, 85.110382, 9.408299,
+ 0.123231, -0.699926, 77.948921, 9.120996, 0.149980, -0.760671, 70.491119, 8.764173, 0.179550,
+ -0.812251, 62.821407, 8.341752, 0.211839, -0.855909, 55.512890, 7.876337, 0.246434, -0.892023,
+ 48.744549, 7.386268, 0.282317, -0.919200, 42.462059, 6.886009, 0.319580, -0.940333, 36.901031,
+ 6.400318, 0.360135, -0.962176, 32.353752, 5.937503, 0.397805, -0.969755, 27.996445, 5.489783,
+ 0.437077, -0.976494, 24.359192, 5.072855, 0.474388, -0.975265, 21.124300, 4.684682, 0.513695,
+ -0.975335, 18.476677, 4.326597, 0.551542, -0.970264, 16.167391, 3.999049, 0.587525, -0.960365,
+ 14.143442, 3.696317, 0.621251, -0.945944, 12.374341, 3.414176, 0.654738, -0.930709, 10.877112,
+ 3.160455, 0.685794, -0.911702, 9.580887, 2.921461, 0.717135, -0.892948, 8.481939, 2.707478,
+ 0.740798, -0.865086, 7.435941, 2.510382, 0.770920, -0.845137, 6.650625, 2.329648, 0.792303,
+ -0.815956, 5.879976, 2.163206, 0.818363, -0.792225, 5.274404, 2.008042, 0.837362, -0.762396,
+ 4.700960, 1.867576, 0.862266, -0.738465, 4.254798, 1.735819, 0.880069, -0.708890, 3.828697,
+ 1.614690, 0.896021, -0.678588, 3.451655, 1.503477, 0.920156, -0.654832, 3.168722, 1.395800,
+ 0.934948, -0.624740, 2.879533, 1.299955, 0.949686, -0.595203, 2.628258, 1.208597, 0.970989,
+ -0.570041, 2.433689, 1.122310, 0.985606, -0.541116, 2.241461, 1.042168, 1.000819, -0.512835,
+ 2.075567, 0.966543, 1.012209, -0.483024, 1.919932, 0.895758, 1.035320, -0.459125, 1.807884,
+ 0.825668, 1.052077, -0.432333, 1.695689, 0.760812, 1.070459, -0.406131, 1.595491, 0.699897,
+ 1.088704, -0.379721, 1.508512, 0.640575, 1.103817, -0.352104, 1.428159, 0.583765, 1.131711,
+ -0.328122, 1.366565, 0.528240, 1.156448, -0.302568, 1.306843, 0.473988, 1.181821, -0.276487,
+ 1.252861, 0.422189, 1.211347, -0.250540, 1.205265, 0.372005, 1.243636, -0.224264, 1.165943,
+ 0.324184, 1.283038, -0.198289, 1.137772, 0.278419, 1.316722, -0.170179, 1.115057, 0.235425,
+ 1.342715, -0.140095, 1.092994, 0.195084, 1.363288, -0.108794, 1.071875, 0.155439, 1.380656,
+ -0.076774, 1.052475, 0.114636, 1.394826, -0.044509, 1.032525, 0.072890, 1.408830, -0.011968,
+ 1.015459, 0.031101, 1.422370, 0.020555, 0.999808, -0.011002, 0.000100, -0.001334, 13.377127,
+ 13.342275, 0.000342, -0.004563, 45.758434, 13.342710, 0.002026, -0.027004, 179.672058,
+ 13.331846, 0.004559, -0.060563, 179.294235, 13.314877, 0.008232, -0.108154, 181.242035,
+ 13.222856, 0.013031, -0.167590, 179.684509, 13.153860, 0.019526, -0.242041, 181.004608,
+ 12.986094, 0.026364, -0.309289, 159.606293, 13.247752, 0.037670, -0.409755, 179.468521,
+ 12.368877, 0.051804, -0.512051, 167.955582, 12.981333, 0.068214, -0.601994, 156.278793,
+ 12.704532, 0.088295, -0.686849, 143.096878, 12.316531, 0.111478, -0.758670, 127.423111,
+ 11.793048, 0.138336, -0.821348, 111.763031, 11.157992, 0.168447, -0.873616, 96.887924,
+ 10.447472, 0.201411, -0.916322, 83.225327, 9.696606, 0.237443, -0.953090, 71.403137, 8.949244,
+ 0.274234, -0.977751, 60.739277, 8.225874, 0.314566, -1.003135, 52.115578, 7.547433, 0.353932,
+ -1.016312, 44.341869, 6.910326, 0.393858, -1.024848, 37.827263, 6.324401, 0.433805, -1.028950,
+ 32.380932, 5.790555, 0.475812, -1.034084, 27.955982, 5.312826, 0.513254, -1.026743, 23.977417,
+ 4.866118, 0.549965, -1.016740, 20.628025, 4.468437, 0.590300, -1.012030, 18.036856, 4.105483,
+ 0.626420, -0.998919, 15.669224, 3.780593, 0.658897, -0.979874, 13.603898, 3.482054, 0.687252,
+ -0.955238, 11.788331, 3.211213, 0.718941, -0.935663, 10.355552, 2.962083, 0.749877, -0.915206,
+ 9.131123, 2.741382, 0.772094, -0.884837, 7.973935, 2.536501, 0.799495, -0.861214, 7.086230,
+ 2.347282, 0.820136, -0.830976, 6.240769, 2.179332, 0.846715, -0.807408, 5.604792, 2.018005,
+ 0.865176, -0.776657, 4.975034, 1.877021, 0.881100, -0.744657, 4.442767, 1.743528, 0.907637,
+ -0.722088, 4.035177, 1.621563, 0.922239, -0.690432, 3.633160, 1.506158, 0.936558, -0.659650,
+ 3.281798, 1.403606, 0.950047, -0.629105, 2.974179, 1.304276, 0.961959, -0.598277, 2.704483,
+ 1.213888, 0.987410, -0.576085, 2.510453, 1.125569, 0.999996, -0.546494, 2.304016, 1.045567,
+ 1.014127, -0.518186, 2.127867, 0.970718, 1.036275, -0.494009, 1.985804, 0.897557, 1.049695,
+ -0.465659, 1.845074, 0.830584, 1.064617, -0.438159, 1.725130, 0.766083, 1.077131, -0.409813,
+ 1.613818, 0.705101, 1.101054, -0.385632, 1.528694, 0.644828, 1.122361, -0.360045, 1.447086,
+ 0.587878, 1.147359, -0.335186, 1.377588, 0.532130, 1.169881, -0.309040, 1.313673, 0.478843,
+ 1.200554, -0.284590, 1.257256, 0.426855, 1.232047, -0.259332, 1.208431, 0.376125, 1.275402,
+ -0.235215, 1.174692, 0.326614, 1.306595, -0.207508, 1.141042, 0.281524, 1.334304, -0.178290,
+ 1.111778, 0.238694, 1.364678, -0.148530, 1.090976, 0.198549, 1.387168, -0.117114, 1.069308,
+ 0.158529, 1.408657, -0.084977, 1.050625, 0.118042, 1.426214, -0.052052, 1.031444, 0.076541,
+ 1.444257, -0.018653, 1.014298, 0.034061, 1.460618, 0.015206, 0.999413, -0.008132, 0.000100,
+ -0.002003, 20.052612, 20.032721, 0.000297, -0.005947, 59.540512, 20.033842, 0.002022,
+ -0.040439, 404.848511, 20.032743, 0.004588, -0.090999, 403.741241, 19.910591, 0.008769,
+ -0.169802, 441.471558, 19.572552, 0.013708, -0.253629, 411.667816, 19.145721, 0.020331,
+ -0.349396, 371.322571, 18.591049, 0.030259, -0.468121, 385.816498, 18.331083, 0.045190,
+ -0.611444, 391.924133, 15.807686, 0.058476, -0.676875, 319.638641, 16.947781, 0.079894,
+ -0.781421, 278.804260, 17.512903, 0.103871, -0.855116, 235.999786, 16.290295, 0.131756,
+ -0.915747, 197.168076, 14.956566, 0.163487, -0.966333, 163.452347, 13.608010, 0.198693,
+ -1.008386, 135.632706, 12.299661, 0.236157, -1.039862, 111.919281, 11.088790, 0.274579,
+ -1.059988, 92.136581, 9.983883, 0.317164, -1.084069, 77.063034, 9.008505, 0.357624, -1.092124,
+ 63.963051, 8.127298, 0.399009, -1.097560, 53.483341, 7.347628, 0.441182, -1.100981, 45.052429,
+ 6.658191, 0.481606, -1.097318, 37.932640, 6.047333, 0.524253, -1.096570, 32.395638, 5.505878,
+ 0.564351, -1.088739, 27.679380, 5.018494, 0.600843, -1.073396, 23.611519, 4.580770, 0.635527,
+ -1.055024, 20.207081, 4.194785, 0.672045, -1.039775, 17.469036, 3.847436, 0.698372, -1.009545,
+ 14.928226, 3.532546, 0.729336, -0.987168, 12.953170, 3.248834, 0.761147, -0.966299, 11.346271,
+ 2.994166, 0.782270, -0.932841, 9.813129, 2.762244, 0.811832, -0.910431, 8.672224, 2.549933,
+ 0.832053, -0.878369, 7.578633, 2.363132, 0.849383, -0.844673, 6.648379, 2.189266, 0.866020,
+ -0.811703, 5.850784, 2.031716, 0.893083, -0.789181, 5.273372, 1.884480, 0.909212, -0.757541,
+ 4.700618, 1.750298, 0.923169, -0.725157, 4.196640, 1.627590, 0.937112, -0.693769, 3.764841,
+ 1.514906, 0.961901, -0.670828, 3.444598, 1.406839, 0.975245, -0.640240, 3.120745, 1.307873,
+ 0.989696, -0.611032, 2.840732, 1.216417, 1.002057, -0.581144, 2.591596, 1.132553, 1.014022,
+ -0.551620, 2.373820, 1.051695, 1.025307, -0.522268, 2.177992, 0.977500, 1.052190, -0.500826,
+ 2.042511, 0.904301, 1.064408, -0.472355, 1.891934, 0.837557, 1.077876, -0.444815, 1.761054,
+ 0.773004, 1.088939, -0.416531, 1.638939, 0.713958, 1.118551, -0.395057, 1.555724, 0.652485,
+ 1.134469, -0.368289, 1.465490, 0.596330, 1.162778, -0.345095, 1.390977, 0.539703, 1.185298,
+ -0.319527, 1.321225, 0.486250, 1.208419, -0.293590, 1.259318, 0.434178, 1.261013, -0.273471,
+ 1.219767, 0.382032, 1.297811, -0.248226, 1.176422, 0.334190, 1.326591, -0.220354, 1.139881,
+ 0.289075, 1.357918, -0.191937, 1.111418, 0.246259, 1.387590, -0.162282, 1.086511, 0.205129,
+ 1.415797, -0.131515, 1.067072, 0.165601, 1.440194, -0.099555, 1.047799, 0.125462, 1.465600,
+ -0.066957, 1.030406, 0.084082, 1.487714, -0.033496, 1.013889, 0.041981, 1.509947, 0.000663,
+ 0.998773, -0.000485, 0.000100, -0.004009, 40.102047, 40.087105, 0.000228, -0.009141, 91.431366,
+ 40.074432, 0.001522, -0.060544, 605.651733, 39.918827, 0.004919, -0.188871, 1712.982300,
+ 38.873421, 0.009053, -0.320325, 1583.453125, 39.715633, 0.015375, -0.471415, 1486.033691,
+ 39.162876, 0.029306, -0.735111, 1751.701050, 28.083200, 0.043450, -0.859759, 1392.475220,
+ 24.599945, 0.079075, -1.220033, 1629.972656, 18.507019, 0.090130, -1.091255, 940.347351,
+ 17.961655, 0.098008, -0.945965, 425.901093, 24.478010, 0.138246, -1.084105, 416.823944,
+ 20.003433, 0.174489, -1.133148, 302.730042, 18.550846, 0.207969, -1.138483, 242.853577,
+ 15.923334, 0.249132, -1.168197, 191.649445, 13.940813, 0.291391, -1.187038, 152.910309,
+ 12.263267, 0.332856, -1.192793, 121.905075, 10.822873, 0.377473, -1.202846, 99.145561,
+ 9.618412, 0.422601, -1.208871, 81.343315, 8.591735, 0.465276, -1.204545, 66.742569, 7.692911,
+ 0.504710, -1.190839, 54.787876, 6.915612, 0.544909, -1.178827, 45.507313, 6.242786, 0.582125,
+ -1.160590, 37.819912, 5.651690, 0.620694, -1.145481, 31.926588, 5.123660, 0.659127, -1.130178,
+ 27.147310, 4.669475, 0.684358, -1.093728, 22.650702, 4.258717, 0.719453, -1.074591, 19.454103,
+ 3.901225, 0.751695, -1.051678, 16.735672, 3.576870, 0.775082, -1.017716, 14.281039, 3.287471,
+ 0.796233, -0.982759, 12.261332, 3.023708, 0.827404, -0.961227, 10.767912, 2.787740, 0.848149,
+ -0.928433, 9.371350, 2.570737, 0.864891, -0.892838, 8.142364, 2.379204, 0.880979, -0.858193,
+ 7.118954, 2.204470, 0.910434, -0.837281, 6.389041, 2.041554, 0.925396, -0.803638, 5.643217,
+ 1.893353, 0.942463, -0.772925, 5.031223, 1.757331, 0.955217, -0.739720, 4.486978, 1.633572,
+ 0.968570, -0.708048, 4.014621, 1.520414, 0.981672, -0.677109, 3.617768, 1.412506, 0.992829,
+ -0.645712, 3.258773, 1.317079, 1.021270, -0.625746, 3.006640, 1.222611, 1.031247, -0.594628,
+ 2.733073, 1.137911, 1.043581, -0.565540, 2.498495, 1.058439, 1.055930, -0.536962, 2.289843,
+ 0.984428, 1.066727, -0.508076, 2.108603, 0.912794, 1.081225, -0.481297, 1.951454, 0.845536,
+ 1.088198, -0.451563, 1.801891, 0.782718, 1.123316, -0.433247, 1.704316, 0.721664, 1.133206,
+ -0.404812, 1.586153, 0.662761, 1.152889, -0.379901, 1.490958, 0.606866, 1.188158, -0.359421,
+ 1.415730, 0.550666, 1.217064, -0.336049, 1.344172, 0.496748, 1.257727, -0.314816, 1.283196,
+ 0.443538, 1.286647, -0.289530, 1.225903, 0.394018, 1.308729, -0.262053, 1.173928, 0.346255,
+ 1.351453, -0.237704, 1.139992, 0.300393, 1.380284, -0.209733, 1.105997, 0.256661, 1.414621,
+ -0.181613, 1.082109, 0.215429, 1.453045, -0.152797, 1.063853, 0.177098, 1.481066, -0.121803,
+ 1.043185, 0.137203, 1.514113, -0.090250, 1.027072, 0.096998, 1.547317, -0.057603, 1.012551,
+ 0.055328, 1.577983, -0.023799, 0.999267, 0.013094, 0.000108, -0.124970, 1249.704346,
+ 1249.703491, 0.000140, -0.119585, 1195.855469, 1195.854370, 0.003995, -0.927433, 9274.246094,
+ 232.443573, 0.012013, -1.131580, 11315.999023, 98.211105, 0.023892, -1.216018, 12162.739258,
+ 67.214500, 0.047506, -1.517865, 15186.294922, 42.410069, 0.082523, -1.812564, 18145.718750,
+ 24.421545, 0.112452, -1.805072, 11112.966797, 18.450365, 0.164460, -2.016784, 8086.032715,
+ 14.043465, 0.195870, -1.898199, 4245.658203, 13.178202, 0.197797, -1.556158, 1315.561768,
+ 30.760096, 0.219540, -1.433455, 802.380371, 25.037956, 0.268696, -1.483235, 579.715515,
+ 20.975695, 0.265968, -1.261051, 386.583649, 12.017023, 0.325369, -1.343349, 316.795959,
+ 12.612406, 0.387968, -1.411606, 232.491623, 13.296940, 0.435543, -1.411236, 181.515228,
+ 11.646996, 0.482729, -1.405722, 143.425354, 10.265131, 0.531742, -1.402782, 114.920082,
+ 9.114828, 0.559383, -1.346165, 88.589005, 8.089214, 0.607851, -1.342407, 73.056610, 7.249064,
+ 0.656928, -1.338238, 60.826897, 6.531094, 0.681212, -1.285692, 48.727219, 5.868711, 0.729238,
+ -1.279951, 41.256016, 5.324553, 0.751172, -1.230045, 33.728260, 4.816513, 0.773107, -1.184288,
+ 27.913816, 4.377203, 0.815726, -1.171653, 24.065962, 3.999965, 0.837886, -1.130636, 20.254860,
+ 3.658493, 0.857674, -1.089071, 17.138168, 3.347930, 0.876120, -1.048303, 14.572968, 3.072666,
+ 0.893935, -1.009040, 12.496377, 2.825165, 0.927998, -0.989064, 11.040731, 2.605520, 0.928445,
+ -0.935017, 9.365102, 2.401481, 0.945279, -0.899993, 8.177711, 2.222282, 0.959378, -0.863854,
+ 7.155303, 2.059342, 0.971761, -0.827684, 6.284632, 1.909314, 0.987812, -0.795878, 5.583837,
+ 1.771094, 1.001958, -0.763540, 4.962345, 1.645968, 1.014357, -0.730897, 4.435898, 1.527438,
+ 1.025946, -0.698675, 3.973241, 1.421337, 1.036435, -0.666662, 3.568025, 1.323677, 1.046807,
+ -0.635466, 3.218647, 1.232678, 1.052974, -0.602660, 2.902273, 1.147675, 1.086089, -0.585364,
+ 2.694939, 1.068352, 1.094660, -0.554784, 2.454491, 0.993445, 1.117131, -0.531500, 2.270746,
+ 0.923758, 1.114009, -0.496581, 2.063934, 0.858381, 1.137328, -0.473914, 1.917990, 0.794980,
+ 1.158671, -0.450127, 1.786523, 0.735697, 1.177878, -0.425306, 1.662454, 0.677498, 1.207510,
+ -0.403797, 1.559058, 0.621762, 1.244496, -0.383812, 1.466801, 0.566190, 1.240412, -0.351080,
+ 1.366853, 0.514288, 1.321257, -0.341200, 1.309808, 0.464621, 1.336512, -0.312710, 1.241822,
+ 0.413228, 1.365047, -0.286935, 1.186612, 0.366092, 1.418984, -0.265184, 1.152120, 0.321528,
+ 1.388864, -0.227750, 1.089937, 0.271827, 1.464383, -0.207168, 1.077271, 0.232838, 1.473125,
+ -0.175770, 1.041835, 0.193289, 1.542908, -0.150424, 1.036794, 0.156153, 1.563005, -0.118748,
+ 1.013029, 0.114866, 1.637048, -0.089604, 1.013493, 0.076804, 1.670777, -0.056398, 0.999208,
+ 0.032691,
+};
+static float ltc_mag_ggx[64 * 64] = {
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999995, 0.999990, 0.999971, 0.999937, 0.999853, 0.999670,
+ 0.999138, 0.996746, 0.979578, 0.979309, 0.978836, 0.977972, 0.976223, 0.972205, 0.962466,
+ 0.953919, 0.949829, 0.942492, 0.929870, 0.921319, 0.911112, 0.896015, 0.885105, 0.869971,
+ 0.855017, 0.838328, 0.821241, 0.802352, 0.783873, 0.763309, 0.743058, 0.721929, 0.699755,
+ 0.677721, 0.655456, 0.632681, 0.609629, 0.586831, 0.564287, 0.541772, 0.519428, 0.497353,
+ 0.475624, 0.454606, 0.434099, 0.414085, 0.394605, 0.375698, 0.357386, 0.339871, 0.323085,
+ 0.306905, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999999, 0.999998, 0.999995, 0.999990, 0.999980, 0.999959, 0.999923, 0.999842,
+ 0.999660, 0.999119, 0.996613, 0.981824, 0.979298, 0.978826, 0.977957, 0.976184, 0.972091,
+ 0.962188, 0.953875, 0.949746, 0.942335, 0.930166, 0.921211, 0.910927, 0.896979, 0.884940,
+ 0.869864, 0.854835, 0.838200, 0.821049, 0.802552, 0.783659, 0.763512, 0.742927, 0.721715,
+ 0.699938, 0.677775, 0.655246, 0.632555, 0.609805, 0.586996, 0.564225, 0.541606, 0.519346,
+ 0.497419, 0.475863, 0.454738, 0.434099, 0.414003, 0.394547, 0.375747, 0.357564, 0.340012,
+ 0.323099, 0.306861, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999991, 0.999979, 0.999959, 0.999917,
+ 0.999839, 0.999648, 0.999074, 0.996168, 0.983770, 0.979279, 0.978800, 0.977905, 0.976058,
+ 0.971727, 0.962120, 0.953901, 0.949485, 0.941859, 0.930911, 0.920853, 0.910394, 0.897600,
+ 0.884427, 0.870101, 0.854522, 0.838325, 0.820754, 0.802707, 0.783223, 0.763605, 0.742872,
+ 0.721565, 0.699935, 0.677726, 0.655242, 0.632580, 0.609766, 0.586946, 0.564275, 0.541759,
+ 0.519467, 0.497478, 0.475886, 0.454794, 0.434233, 0.414207, 0.394751, 0.375892, 0.357683,
+ 0.340146, 0.323287, 0.307095, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999999, 0.999998, 0.999996, 0.999992, 0.999987, 0.999975, 0.999953,
+ 0.999913, 0.999830, 0.999630, 0.998993, 0.995279, 0.985142, 0.979252, 0.978754, 0.977821,
+ 0.975838, 0.971088, 0.962563, 0.954785, 0.949048, 0.941052, 0.931420, 0.920812, 0.909750,
+ 0.897867, 0.883856, 0.870091, 0.854353, 0.838166, 0.820661, 0.802465, 0.783308, 0.763346,
+ 0.742734, 0.721608, 0.699747, 0.677626, 0.655245, 0.632547, 0.609793, 0.587044, 0.564340,
+ 0.541779, 0.519529, 0.497633, 0.476114, 0.455030, 0.434430, 0.414406, 0.394974, 0.376154,
+ 0.357979, 0.340443, 0.323572, 0.307379, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999998, 0.999998, 0.999996, 0.999991, 0.999984, 0.999970,
+ 0.999946, 0.999905, 0.999815, 0.999599, 0.998856, 0.993704, 0.986135, 0.979212, 0.978690,
+ 0.977691, 0.975504, 0.970133, 0.962951, 0.955649, 0.948405, 0.940418, 0.931660, 0.920881,
+ 0.909376, 0.897785, 0.883844, 0.869756, 0.854326, 0.837732, 0.820617, 0.802053, 0.783195,
+ 0.763119, 0.742610, 0.721344, 0.699709, 0.677624, 0.655114, 0.632523, 0.609812, 0.587052,
+ 0.564417, 0.541966, 0.519751, 0.497824, 0.476309, 0.455271, 0.434735, 0.414736, 0.395317,
+ 0.376524, 0.358364, 0.340852, 0.323988, 0.307786, 1.000000, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999999, 0.999997, 0.999996, 0.999994, 0.999989, 0.999980,
+ 0.999965, 0.999940, 0.999895, 0.999796, 0.999559, 0.998638, 0.992774, 0.986878, 0.980297,
+ 0.978602, 0.977514, 0.975026, 0.969169, 0.963214, 0.956267, 0.947689, 0.940054, 0.931637,
+ 0.920678, 0.908990, 0.897349, 0.883905, 0.869139, 0.854177, 0.837476, 0.820295, 0.801977,
+ 0.782798, 0.762978, 0.742418, 0.721193, 0.699560, 0.677402, 0.655108, 0.632543, 0.609804,
+ 0.587158, 0.564557, 0.542096, 0.519908, 0.498088, 0.476632, 0.455623, 0.435104, 0.415161,
+ 0.395783, 0.377005, 0.358843, 0.341345, 0.324529, 0.308355, 1.000000, 1.000000, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999999, 0.999998, 0.999997, 0.999992, 0.999991, 0.999985,
+ 0.999977, 0.999959, 0.999935, 0.999878, 0.999773, 0.999505, 0.998284, 0.992353, 0.987457,
+ 0.981665, 0.978492, 0.977277, 0.974360, 0.968716, 0.963373, 0.956629, 0.947397, 0.939657,
+ 0.931339, 0.920588, 0.908975, 0.896712, 0.883763, 0.868890, 0.853731, 0.837333, 0.819702,
+ 0.801738, 0.782454, 0.762712, 0.742024, 0.721037, 0.699325, 0.677359, 0.655030, 0.632439,
+ 0.609869, 0.587221, 0.564663, 0.542328, 0.520220, 0.498400, 0.476997, 0.456053, 0.435593,
+ 0.415658, 0.396300, 0.377577, 0.359473, 0.342004, 0.325170, 0.308997, 1.000000, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999998, 0.999996, 0.999993, 0.999988,
+ 0.999981, 0.999971, 0.999951, 0.999921, 0.999863, 0.999748, 0.999433, 0.997681, 0.992120,
+ 0.987920, 0.982864, 0.978353, 0.976961, 0.973451, 0.968396, 0.963400, 0.956680, 0.947529,
+ 0.939151, 0.930747, 0.920511, 0.908867, 0.896142, 0.883335, 0.868764, 0.853025, 0.837015,
+ 0.819452, 0.801249, 0.782176, 0.762345, 0.741843, 0.720721, 0.699135, 0.677194, 0.654889,
+ 0.632487, 0.609902, 0.587328, 0.564891, 0.542567, 0.520501, 0.498793, 0.477442, 0.456528,
+ 0.436131, 0.416273, 0.396980, 0.378276, 0.360176, 0.342738, 0.325950, 0.309803, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999999, 0.999997, 0.999995, 0.999991,
+ 0.999985, 0.999978, 0.999963, 0.999942, 0.999907, 0.999844, 0.999715, 0.999332, 0.996612,
+ 0.991974, 0.988297, 0.983843, 0.978349, 0.976540, 0.972351, 0.968109, 0.963280, 0.956464,
+ 0.947779, 0.938754, 0.929952, 0.920253, 0.908530, 0.895785, 0.882679, 0.868456, 0.852669,
+ 0.836406, 0.819138, 0.800708, 0.781803, 0.761855, 0.741534, 0.720405, 0.698959, 0.676964,
+ 0.654827, 0.632411, 0.609922, 0.587477, 0.565051, 0.542829, 0.520889, 0.499225, 0.477951,
+ 0.457148, 0.436792, 0.416963, 0.397723, 0.379068, 0.361025, 0.343608, 0.326842, 0.310718,
+ 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999994,
+ 0.999990, 0.999983, 0.999971, 0.999954, 0.999932, 0.999892, 0.999820, 0.999675, 0.999190,
+ 0.995492, 0.991911, 0.988610, 0.984662, 0.979221, 0.975975, 0.971671, 0.967788, 0.963002,
+ 0.955938, 0.947965, 0.938692, 0.929309, 0.919781, 0.908268, 0.895518, 0.882022, 0.867884,
+ 0.852346, 0.835746, 0.818607, 0.800261, 0.781335, 0.761539, 0.741063, 0.720116, 0.698617,
+ 0.676815, 0.654700, 0.632389, 0.610037, 0.587591, 0.565328, 0.543205, 0.521293, 0.499745,
+ 0.478562, 0.457776, 0.437515, 0.417776, 0.398586, 0.379963, 0.361984, 0.344616, 0.327857,
+ 0.311751, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997, 0.999996,
+ 0.999992, 0.999986, 0.999977, 0.999965, 0.999947, 0.999916, 0.999873, 0.999794, 0.999628,
+ 0.998966, 0.994914, 0.991849, 0.988873, 0.985288, 0.980170, 0.975207, 0.971156, 0.967476,
+ 0.962538, 0.955601, 0.947978, 0.938542, 0.928618, 0.919056, 0.907890, 0.895098, 0.881352,
+ 0.867263, 0.851806, 0.835168, 0.818003, 0.799785, 0.780633, 0.761080, 0.740618, 0.719795,
+ 0.698332, 0.676629, 0.654544, 0.632411, 0.610042, 0.587805, 0.565593, 0.543549, 0.521793,
+ 0.500309, 0.479195, 0.458546, 0.438353, 0.418669, 0.399557, 0.381012, 0.363049, 0.345710,
+ 0.329006, 0.312948, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997,
+ 0.999993, 0.999990, 0.999984, 0.999972, 0.999960, 0.999939, 0.999906, 0.999853, 0.999765,
+ 0.999567, 0.998603, 0.994519, 0.991794, 0.989089, 0.985781, 0.980956, 0.974161, 0.970688,
+ 0.967064, 0.961890, 0.955292, 0.947848, 0.938359, 0.928226, 0.918214, 0.907361, 0.894702,
+ 0.880834, 0.866500, 0.851209, 0.834627, 0.817211, 0.799250, 0.780131, 0.760512, 0.740218,
+ 0.719264, 0.698063, 0.676325, 0.654450, 0.632316, 0.610170, 0.587988, 0.565891, 0.544013,
+ 0.522305, 0.500958, 0.479971, 0.459376, 0.439271, 0.419699, 0.400620, 0.382126, 0.364246,
+ 0.346967, 0.330273, 0.314236, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998,
+ 0.999996, 0.999994, 0.999988, 0.999979, 0.999967, 0.999952, 0.999924, 0.999888, 0.999833,
+ 0.999733, 0.999490, 0.997946, 0.994192, 0.991812, 0.989274, 0.986224, 0.981547, 0.974000,
+ 0.970269, 0.966545, 0.961031, 0.954921, 0.947416, 0.938226, 0.928003, 0.917390, 0.906553,
+ 0.894191, 0.880329, 0.865540, 0.850476, 0.834058, 0.816467, 0.798509, 0.779561, 0.759828,
+ 0.739738, 0.718878, 0.697718, 0.676138, 0.654342, 0.632317, 0.610292, 0.588207, 0.566289,
+ 0.544443, 0.522927, 0.501674, 0.480765, 0.460314, 0.440304, 0.420782, 0.401824, 0.383410,
+ 0.365538, 0.348312, 0.331692, 0.315688, 1.000000, 1.000000, 1.000000, 1.000000, 0.999999,
+ 0.999998, 0.999996, 0.999993, 0.999985, 0.999976, 0.999961, 0.999943, 0.999913, 0.999872,
+ 0.999807, 0.999691, 0.999390, 0.996859, 0.994003, 0.991808, 0.989423, 0.986523, 0.981783,
+ 0.974511, 0.969791, 0.965933, 0.960377, 0.954434, 0.946803, 0.938026, 0.927620, 0.916545,
+ 0.905639, 0.893489, 0.879820, 0.864852, 0.849513, 0.833311, 0.815878, 0.797621, 0.778938,
+ 0.759253, 0.739142, 0.718479, 0.697274, 0.675902, 0.654135, 0.632357, 0.610364, 0.588497,
+ 0.566631, 0.545012, 0.523579, 0.502429, 0.481680, 0.461304, 0.441425, 0.422039, 0.403135,
+ 0.384779, 0.366976, 0.349796, 0.333231, 0.317277, 1.000000, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999998, 0.999996, 0.999991, 0.999983, 0.999974, 0.999956, 0.999932, 0.999901,
+ 0.999852, 0.999780, 0.999646, 0.999248, 0.996193, 0.993784, 0.991782, 0.989539, 0.986694,
+ 0.981765, 0.975135, 0.969309, 0.965128, 0.959788, 0.953831, 0.946255, 0.937664, 0.927351,
+ 0.916044, 0.904715, 0.892528, 0.879111, 0.864256, 0.848452, 0.832434, 0.815129, 0.796806,
+ 0.778118, 0.758668, 0.738466, 0.718024, 0.696958, 0.675642, 0.654067, 0.632325, 0.610546,
+ 0.588786, 0.567123, 0.545617, 0.524312, 0.503348, 0.482637, 0.462418, 0.442657, 0.423338,
+ 0.404564, 0.386277, 0.368545, 0.351448, 0.334906, 0.318961, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999999, 0.999998, 0.999994, 0.999989, 0.999979, 0.999968, 0.999949, 0.999921,
+ 0.999886, 0.999833, 0.999747, 0.999596, 0.999029, 0.995749, 0.993677, 0.991724, 0.989620,
+ 0.986723, 0.981515, 0.975767, 0.969056, 0.964124, 0.959142, 0.953036, 0.945650, 0.937022,
+ 0.926971, 0.915515, 0.903584, 0.891603, 0.878212, 0.863472, 0.847652, 0.831398, 0.814299,
+ 0.796105, 0.777231, 0.757977, 0.737895, 0.717415, 0.696595, 0.675317, 0.653980, 0.632343,
+ 0.610735, 0.589076, 0.567620, 0.546251, 0.525165, 0.504255, 0.483759, 0.463666, 0.443987,
+ 0.424783, 0.406042, 0.387891, 0.370293, 0.353221, 0.336715, 0.320806, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999998, 0.999998, 0.999993, 0.999987, 0.999977, 0.999964, 0.999943,
+ 0.999911, 0.999867, 0.999807, 0.999714, 0.999531, 0.998645, 0.995399, 0.993512, 0.991717,
+ 0.989661, 0.986652, 0.981559, 0.976183, 0.969411, 0.963317, 0.958457, 0.952091, 0.944951,
+ 0.936307, 0.926454, 0.915043, 0.902668, 0.890462, 0.877245, 0.862672, 0.846823, 0.830201,
+ 0.813293, 0.795306, 0.776393, 0.757199, 0.737324, 0.716808, 0.696187, 0.675094, 0.653814,
+ 0.632453, 0.610885, 0.589483, 0.568099, 0.546975, 0.525953, 0.505268, 0.484936, 0.464988,
+ 0.445458, 0.426314, 0.407750, 0.389670, 0.372098, 0.355105, 0.338682, 0.322825, 1.000000,
+ 1.000000, 1.000000, 1.000000, 0.999999, 0.999996, 0.999992, 0.999983, 0.999976, 0.999959,
+ 0.999933, 0.999898, 0.999849, 0.999780, 0.999676, 0.999454, 0.997884, 0.995166, 0.993394,
+ 0.991723, 0.989654, 0.986389, 0.981632, 0.976607, 0.969701, 0.962555, 0.957605, 0.951232,
+ 0.944099, 0.935556, 0.925699, 0.914492, 0.902027, 0.889116, 0.876093, 0.861649, 0.845956,
+ 0.829238, 0.812220, 0.794420, 0.775657, 0.756265, 0.736673, 0.716372, 0.695669, 0.674886,
+ 0.653728, 0.632568, 0.611217, 0.589929, 0.568783, 0.547752, 0.526931, 0.506425, 0.486238,
+ 0.466425, 0.446945, 0.428026, 0.409536, 0.391551, 0.374087, 0.357155, 0.340787, 0.324974,
+ 1.000000, 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999990, 0.999984, 0.999970,
+ 0.999952, 0.999925, 0.999886, 0.999831, 0.999757, 0.999633, 0.999356, 0.997017, 0.994868,
+ 0.993337, 0.991710, 0.989580, 0.985848, 0.981640, 0.976711, 0.969755, 0.962166, 0.956609,
+ 0.950365, 0.943026, 0.934693, 0.924880, 0.913729, 0.901350, 0.887966, 0.874726, 0.860474,
+ 0.844905, 0.828269, 0.810905, 0.793364, 0.774812, 0.755478, 0.735886, 0.715847, 0.695231,
+ 0.674537, 0.653667, 0.632527, 0.611475, 0.590363, 0.569462, 0.548571, 0.527976, 0.507634,
+ 0.487632, 0.467901, 0.448680, 0.429833, 0.411467, 0.393568, 0.376197, 0.359374, 0.343034,
+ 0.327273, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999993, 0.999989, 0.999980,
+ 0.999965, 0.999945, 0.999913, 0.999869, 0.999810, 0.999723, 0.999583, 0.999213, 0.996540,
+ 0.994740, 0.993244, 0.991671, 0.989411, 0.985533, 0.981616, 0.976847, 0.969968, 0.962315,
+ 0.955468, 0.949420, 0.942016, 0.933617, 0.923949, 0.912899, 0.900495, 0.887022, 0.873283,
+ 0.859153, 0.843830, 0.827325, 0.809888, 0.792172, 0.773832, 0.754686, 0.735035, 0.715297,
+ 0.694955, 0.674242, 0.653660, 0.632752, 0.611804, 0.590993, 0.570154, 0.549539, 0.529087,
+ 0.508974, 0.489030, 0.469599, 0.450466, 0.431761, 0.413508, 0.395761, 0.378480, 0.361679,
+ 0.345465, 0.329752, 1.000000, 1.000000, 1.000000, 1.000000, 0.999997, 0.999994, 0.999987,
+ 0.999978, 0.999961, 0.999936, 0.999903, 0.999855, 0.999786, 0.999689, 0.999527, 0.998988,
+ 0.996137, 0.994527, 0.993108, 0.991599, 0.989084, 0.985308, 0.981527, 0.976677, 0.970079,
+ 0.962535, 0.954490, 0.948271, 0.940942, 0.932422, 0.922836, 0.911896, 0.899632, 0.886118,
+ 0.871864, 0.857719, 0.842536, 0.826163, 0.808849, 0.790860, 0.772802, 0.753860, 0.734335,
+ 0.714582, 0.694543, 0.674071, 0.653544, 0.632922, 0.612153, 0.591573, 0.570951, 0.550520,
+ 0.530352, 0.510311, 0.490707, 0.471359, 0.452396, 0.433837, 0.415736, 0.398052, 0.380874,
+ 0.364232, 0.348023, 0.332368, 1.000000, 1.000000, 1.000000, 0.999999, 0.999998, 0.999994,
+ 0.999988, 0.999976, 0.999957, 0.999928, 0.999891, 0.999837, 0.999759, 0.999650, 0.999463,
+ 0.998551, 0.995879, 0.994366, 0.992964, 0.991479, 0.988521, 0.985101, 0.981482, 0.976168,
+ 0.970242, 0.962585, 0.953950, 0.946973, 0.939686, 0.931248, 0.921614, 0.910765, 0.898617,
+ 0.885183, 0.870772, 0.856138, 0.841120, 0.824962, 0.807732, 0.789813, 0.771638, 0.753008,
+ 0.733686, 0.713927, 0.694082, 0.673967, 0.653549, 0.633135, 0.612702, 0.592200, 0.571904,
+ 0.551679, 0.531678, 0.511898, 0.492437, 0.473239, 0.454451, 0.436067, 0.418054, 0.400542,
+ 0.383486, 0.366848, 0.350781, 0.335182, 1.000000, 1.000000, 1.000000, 0.999999, 0.999997,
+ 0.999993, 0.999985, 0.999972, 0.999951, 0.999919, 0.999877, 0.999817, 0.999733, 0.999608,
+ 0.999380, 0.997685, 0.995603, 0.994264, 0.992911, 0.991287, 0.987923, 0.984871, 0.981239,
+ 0.975933, 0.970149, 0.962511, 0.953824, 0.945699, 0.938285, 0.929907, 0.920343, 0.909537,
+ 0.897435, 0.884056, 0.869626, 0.854490, 0.839459, 0.823511, 0.806511, 0.788752, 0.770440,
+ 0.751995, 0.732962, 0.713424, 0.693525, 0.673798, 0.653622, 0.633301, 0.613224, 0.592938,
+ 0.572833, 0.552904, 0.533030, 0.513556, 0.494215, 0.475279, 0.456673, 0.438411, 0.420583,
+ 0.403178, 0.386178, 0.369728, 0.353688, 0.338147, 1.000000, 1.000000, 1.000000, 0.999999,
+ 0.999997, 0.999991, 0.999984, 0.999967, 0.999944, 0.999912, 0.999863, 0.999796, 0.999703,
+ 0.999563, 0.999279, 0.997104, 0.995394, 0.994111, 0.992825, 0.990979, 0.987529, 0.984661,
+ 0.980774, 0.975758, 0.969866, 0.962465, 0.953678, 0.944489, 0.936886, 0.928356, 0.918820,
+ 0.908073, 0.896092, 0.882833, 0.868463, 0.853212, 0.837744, 0.822048, 0.805333, 0.787643,
+ 0.769414, 0.750830, 0.732178, 0.712972, 0.693227, 0.673569, 0.653744, 0.633739, 0.613735,
+ 0.593822, 0.573916, 0.554158, 0.534652, 0.515248, 0.496233, 0.477436, 0.459009, 0.440929,
+ 0.423259, 0.405951, 0.389136, 0.372690, 0.356789, 0.341329, 1.000000, 1.000000, 1.000000,
+ 0.999999, 0.999996, 0.999991, 0.999981, 0.999966, 0.999939, 0.999903, 0.999847, 0.999771,
+ 0.999666, 0.999510, 0.999131, 0.996690, 0.995147, 0.993882, 0.992696, 0.990474, 0.987227,
+ 0.984334, 0.980153, 0.975438, 0.969406, 0.962238, 0.953598, 0.943868, 0.935356, 0.926721,
+ 0.917122, 0.906430, 0.894550, 0.881354, 0.867131, 0.851954, 0.835972, 0.820331, 0.803911,
+ 0.786452, 0.768420, 0.749821, 0.731298, 0.712393, 0.692979, 0.673418, 0.653859, 0.634232,
+ 0.614327, 0.594732, 0.575131, 0.555584, 0.536346, 0.517175, 0.498323, 0.479744, 0.461485,
+ 0.443645, 0.426061, 0.408969, 0.392155, 0.375921, 0.360060, 0.344677, 1.000000, 1.000000,
+ 1.000000, 0.999999, 0.999997, 0.999991, 0.999979, 0.999960, 0.999931, 0.999891, 0.999832,
+ 0.999748, 0.999629, 0.999449, 0.998880, 0.996305, 0.995024, 0.993812, 0.992508, 0.989721,
+ 0.986936, 0.983936, 0.979629, 0.974979, 0.968928, 0.961970, 0.953291, 0.943458, 0.933644,
+ 0.925007, 0.915388, 0.904755, 0.892932, 0.879831, 0.865794, 0.850672, 0.834591, 0.818398,
+ 0.802304, 0.785151, 0.767450, 0.748987, 0.730325, 0.711758, 0.692761, 0.673417, 0.653908,
+ 0.634686, 0.615168, 0.595707, 0.576393, 0.557198, 0.538018, 0.519253, 0.500555, 0.482220,
+ 0.464197, 0.446414, 0.429106, 0.412035, 0.395508, 0.379284, 0.363538, 0.348220, 1.000000,
+ 1.000000, 1.000000, 0.999999, 0.999995, 0.999989, 0.999977, 0.999955, 0.999924, 0.999879,
+ 0.999813, 0.999722, 0.999590, 0.999381, 0.998335, 0.996088, 0.994814, 0.993709, 0.992220,
+ 0.989209, 0.986575, 0.983383, 0.979084, 0.974272, 0.968359, 0.961275, 0.953025, 0.943098,
+ 0.932434, 0.923101, 0.913477, 0.902861, 0.891059, 0.878072, 0.864118, 0.849188, 0.833281,
+ 0.816808, 0.800596, 0.783745, 0.766331, 0.748123, 0.729686, 0.711078, 0.692527, 0.673491,
+ 0.654296, 0.635113, 0.616048, 0.596847, 0.577720, 0.558879, 0.540028, 0.521371, 0.502996,
+ 0.484858, 0.466997, 0.449477, 0.432217, 0.415426, 0.398924, 0.382890, 0.367206, 0.351955,
+ 1.000000, 1.000000, 1.000000, 0.999998, 0.999996, 0.999988, 0.999974, 0.999953, 0.999918,
+ 0.999865, 0.999791, 0.999690, 0.999542, 0.999293, 0.997535, 0.995790, 0.994609, 0.993557,
+ 0.991766, 0.988767, 0.986255, 0.982544, 0.978541, 0.973528, 0.967700, 0.960596, 0.952299,
+ 0.942684, 0.931653, 0.921211, 0.911489, 0.900818, 0.889018, 0.876245, 0.862406, 0.847517,
+ 0.831852, 0.815367, 0.798719, 0.782224, 0.765167, 0.747304, 0.729133, 0.710485, 0.692196,
+ 0.673589, 0.654770, 0.635717, 0.616986, 0.598119, 0.579298, 0.560560, 0.542163, 0.523669,
+ 0.505564, 0.487642, 0.469991, 0.452658, 0.435620, 0.418937, 0.402612, 0.386633, 0.371091,
+ 0.355949, 1.000000, 1.000000, 0.999999, 0.999998, 0.999995, 0.999986, 0.999973, 0.999948,
+ 0.999909, 0.999852, 0.999769, 0.999656, 0.999490, 0.999186, 0.997059, 0.995624, 0.994510,
+ 0.993327, 0.991020, 0.988379, 0.985771, 0.981971, 0.978051, 0.972892, 0.967020, 0.959965,
+ 0.951625, 0.941902, 0.930951, 0.919370, 0.909285, 0.898562, 0.886809, 0.874251, 0.860597,
+ 0.845808, 0.830365, 0.813972, 0.797260, 0.780597, 0.763854, 0.746401, 0.728519, 0.710203,
+ 0.691882, 0.673687, 0.655275, 0.636621, 0.617909, 0.599473, 0.581032, 0.562560, 0.544295,
+ 0.526228, 0.508293, 0.490652, 0.473242, 0.456004, 0.439212, 0.422663, 0.406476, 0.390647,
+ 0.375204, 0.360129, 1.000000, 1.000000, 1.000000, 0.999999, 0.999994, 0.999984, 0.999969,
+ 0.999940, 0.999898, 0.999837, 0.999746, 0.999617, 0.999438, 0.999016, 0.996703, 0.995302,
+ 0.994356, 0.992993, 0.990390, 0.988072, 0.985152, 0.981447, 0.977273, 0.972234, 0.966113,
+ 0.959033, 0.950869, 0.941217, 0.930175, 0.918279, 0.906941, 0.896201, 0.884509, 0.871920,
+ 0.858420, 0.843906, 0.828730, 0.812524, 0.795978, 0.778979, 0.762450, 0.745459, 0.727966,
+ 0.710046, 0.691808, 0.673739, 0.655756, 0.637574, 0.619153, 0.600887, 0.582796, 0.564748,
+ 0.546636, 0.528904, 0.511252, 0.493791, 0.476563, 0.459695, 0.442942, 0.426632, 0.410558,
+ 0.394895, 0.379517, 0.364560, 1.000000, 1.000000, 1.000000, 0.999998, 0.999994, 0.999984,
+ 0.999966, 0.999934, 0.999887, 0.999819, 0.999720, 0.999578, 0.999367, 0.998696, 0.996353,
+ 0.995201, 0.994115, 0.992665, 0.989948, 0.987633, 0.984331, 0.980827, 0.976390, 0.971327,
+ 0.965201, 0.957977, 0.949712, 0.940128, 0.929187, 0.917237, 0.904645, 0.893711, 0.882112,
+ 0.869516, 0.856236, 0.841929, 0.826924, 0.810991, 0.794686, 0.777761, 0.760980, 0.744384,
+ 0.727314, 0.709877, 0.691988, 0.674098, 0.656243, 0.638603, 0.620606, 0.602574, 0.584694,
+ 0.567018, 0.549311, 0.531673, 0.514403, 0.497148, 0.480177, 0.463439, 0.446998, 0.430743,
+ 0.414943, 0.399304, 0.384121, 0.369251, 1.000000, 1.000000, 1.000000, 0.999997, 0.999992,
+ 0.999981, 0.999962, 0.999927, 0.999874, 0.999798, 0.999691, 0.999533, 0.999291, 0.997909,
+ 0.996117, 0.995029, 0.993880, 0.992142, 0.989576, 0.987185, 0.983587, 0.980055, 0.975487,
+ 0.970172, 0.963998, 0.956738, 0.948637, 0.939083, 0.928169, 0.916144, 0.903147, 0.890916,
+ 0.879389, 0.866895, 0.853826, 0.839729, 0.824957, 0.809472, 0.793341, 0.776743, 0.759808,
+ 0.743277, 0.726643, 0.709685, 0.692249, 0.674639, 0.657008, 0.639576, 0.622114, 0.604471,
+ 0.586851, 0.569340, 0.552135, 0.534806, 0.517599, 0.500765, 0.484035, 0.467440, 0.451212,
+ 0.435240, 0.419399, 0.404083, 0.388944, 0.374182, 1.000000, 1.000000, 1.000000, 0.999998,
+ 0.999993, 0.999979, 0.999958, 0.999919, 0.999861, 0.999774, 0.999656, 0.999482, 0.999195,
+ 0.997307, 0.995837, 0.994722, 0.993707, 0.991391, 0.989169, 0.986461, 0.982904, 0.979062,
+ 0.974536, 0.969035, 0.962653, 0.955486, 0.947243, 0.937747, 0.926861, 0.914936, 0.901835,
+ 0.888472, 0.876571, 0.864223, 0.851252, 0.837374, 0.822985, 0.807788, 0.791927, 0.775702,
+ 0.758928, 0.742347, 0.725914, 0.709495, 0.692569, 0.675363, 0.658085, 0.640639, 0.623698,
+ 0.606505, 0.589267, 0.572008, 0.554939, 0.538132, 0.521211, 0.504487, 0.488048, 0.471807,
+ 0.455651, 0.439858, 0.424332, 0.408983, 0.394071, 0.379402, 1.000000, 1.000000, 1.000000,
+ 0.999997, 0.999992, 0.999978, 0.999954, 0.999913, 0.999844, 0.999753, 0.999618, 0.999424,
+ 0.999067, 0.996875, 0.995659, 0.994603, 0.993420, 0.990874, 0.988713, 0.985585, 0.982193,
+ 0.978145, 0.973416, 0.967801, 0.961483, 0.954069, 0.945704, 0.936138, 0.925374, 0.913395,
+ 0.900339, 0.886675, 0.873512, 0.861326, 0.848513, 0.834956, 0.820820, 0.805943, 0.790574,
+ 0.774677, 0.758279, 0.741807, 0.725271, 0.709231, 0.692874, 0.676189, 0.659352, 0.642296,
+ 0.625250, 0.608700, 0.591823, 0.575012, 0.558143, 0.541491, 0.525075, 0.508558, 0.492277,
+ 0.476270, 0.460459, 0.444740, 0.429400, 0.414309, 0.399421, 0.384907, 1.000000, 1.000000,
+ 1.000000, 0.999997, 0.999990, 0.999977, 0.999947, 0.999902, 0.999832, 0.999730, 0.999577,
+ 0.999359, 0.998845, 0.996554, 0.995328, 0.994442, 0.992919, 0.990393, 0.988170, 0.984855,
+ 0.981312, 0.977149, 0.972137, 0.966207, 0.959967, 0.952454, 0.943873, 0.934434, 0.923813,
+ 0.911942, 0.898928, 0.885120, 0.871043, 0.858248, 0.845666, 0.832346, 0.818482, 0.804029,
+ 0.788982, 0.773571, 0.757700, 0.741484, 0.725186, 0.708915, 0.693244, 0.677028, 0.660656,
+ 0.644079, 0.627377, 0.610804, 0.594542, 0.578112, 0.561650, 0.545163, 0.528962, 0.512926,
+ 0.496893, 0.481007, 0.465397, 0.450042, 0.434740, 0.419831, 0.405156, 0.390692, 1.000000,
+ 1.000000, 0.999999, 0.999997, 0.999989, 0.999973, 0.999942, 0.999891, 0.999813, 0.999698,
+ 0.999532, 0.999285, 0.998286, 0.996295, 0.995215, 0.994182, 0.992032, 0.989855, 0.987415,
+ 0.984047, 0.980050, 0.976017, 0.970845, 0.964767, 0.958269, 0.950600, 0.942033, 0.932501,
+ 0.921807, 0.910017, 0.897149, 0.883414, 0.869182, 0.855055, 0.842687, 0.829548, 0.816162,
+ 0.802072, 0.787436, 0.772533, 0.757043, 0.741263, 0.725330, 0.709262, 0.693497, 0.678038,
+ 0.662128, 0.646068, 0.629824, 0.613437, 0.597334, 0.581401, 0.565372, 0.549288, 0.533182,
+ 0.517405, 0.501765, 0.486143, 0.470675, 0.455465, 0.440532, 0.425630, 0.411113, 0.396887,
+ 1.000000, 1.000000, 0.999999, 0.999996, 0.999989, 0.999970, 0.999934, 0.999879, 0.999793,
+ 0.999665, 0.999481, 0.999192, 0.997506, 0.995926, 0.995009, 0.993736, 0.991298, 0.989326,
+ 0.986371, 0.983199, 0.979032, 0.974596, 0.969364, 0.963198, 0.956385, 0.948509, 0.939993,
+ 0.930421, 0.919590, 0.908140, 0.895349, 0.881699, 0.867456, 0.852784, 0.839500, 0.826629,
+ 0.813602, 0.799983, 0.785873, 0.771340, 0.756480, 0.741190, 0.725687, 0.709997, 0.694192,
+ 0.678975, 0.663673, 0.648135, 0.632442, 0.616477, 0.600565, 0.584772, 0.569202, 0.553595,
+ 0.537881, 0.522193, 0.506784, 0.491554, 0.476349, 0.461278, 0.446419, 0.431913, 0.417443,
+ 0.403271, 1.000000, 1.000000, 0.999999, 0.999995, 0.999986, 0.999966, 0.999927, 0.999867,
+ 0.999772, 0.999629, 0.999423, 0.999075, 0.997024, 0.995773, 0.994651, 0.993353, 0.990822,
+ 0.988569, 0.985596, 0.982182, 0.977871, 0.973140, 0.967584, 0.961408, 0.954294, 0.946398,
+ 0.937603, 0.927937, 0.917305, 0.905833, 0.893138, 0.879770, 0.865720, 0.851023, 0.836801,
+ 0.823784, 0.810909, 0.797886, 0.784177, 0.770243, 0.755925, 0.741144, 0.726214, 0.710971,
+ 0.695563, 0.680212, 0.665304, 0.650297, 0.635168, 0.619796, 0.604217, 0.588692, 0.573254,
+ 0.557998, 0.542839, 0.527470, 0.512162, 0.497115, 0.482296, 0.467477, 0.452812, 0.438310,
+ 0.424184, 0.410163, 1.000000, 1.000000, 0.999999, 0.999996, 0.999984, 0.999962, 0.999920,
+ 0.999852, 0.999745, 0.999586, 0.999354, 0.998894, 0.996686, 0.995485, 0.994493, 0.992573,
+ 0.990323, 0.987772, 0.984692, 0.980887, 0.976446, 0.971625, 0.965717, 0.959421, 0.951975,
+ 0.944086, 0.935066, 0.925403, 0.914814, 0.903208, 0.890958, 0.877817, 0.863828, 0.849289,
+ 0.834872, 0.820889, 0.808183, 0.795660, 0.782556, 0.769066, 0.755386, 0.741229, 0.726726,
+ 0.712170, 0.697209, 0.682170, 0.667203, 0.652689, 0.637938, 0.623262, 0.608190, 0.593002,
+ 0.577817, 0.562737, 0.547836, 0.533036, 0.518052, 0.503135, 0.488422, 0.473986, 0.459552,
+ 0.445282, 0.431149, 0.417407, 1.000000, 1.000000, 0.999999, 0.999994, 0.999983, 0.999957,
+ 0.999914, 0.999835, 0.999718, 0.999538, 0.999275, 0.998454, 0.996341, 0.995246, 0.994222,
+ 0.991844, 0.989829, 0.986688, 0.983562, 0.979638, 0.974932, 0.969827, 0.963621, 0.957146,
+ 0.949365, 0.941398, 0.932245, 0.922556, 0.911949, 0.900627, 0.888440, 0.875544, 0.862005,
+ 0.847810, 0.833372, 0.819134, 0.805508, 0.793339, 0.780916, 0.767837, 0.754858, 0.741307,
+ 0.727496, 0.713386, 0.699131, 0.684542, 0.669878, 0.655261, 0.641035, 0.626685, 0.612377,
+ 0.597625, 0.582805, 0.568030, 0.553204, 0.538684, 0.524269, 0.509662, 0.495119, 0.480735,
+ 0.466634, 0.452593, 0.438748, 0.424915, 1.000000, 1.000000, 0.999998, 0.999994, 0.999982,
+ 0.999956, 0.999901, 0.999818, 0.999683, 0.999487, 0.999185, 0.997584, 0.996004, 0.995050,
+ 0.993715, 0.991212, 0.989057, 0.985879, 0.982243, 0.978206, 0.973119, 0.967919, 0.961343,
+ 0.954603, 0.946712, 0.938378, 0.929266, 0.919443, 0.908911, 0.897725, 0.885589, 0.873254,
+ 0.859889, 0.846123, 0.832094, 0.817898, 0.803866, 0.791061, 0.779235, 0.766885, 0.754292,
+ 0.741565, 0.728331, 0.714861, 0.701179, 0.687166, 0.673012, 0.658716, 0.644442, 0.630472,
+ 0.616519, 0.602514, 0.588172, 0.573689, 0.559281, 0.544768, 0.530543, 0.516485, 0.502303,
+ 0.488100, 0.474095, 0.460245, 0.446598, 0.433169, 1.000000, 1.000000, 0.999997, 0.999993,
+ 0.999980, 0.999947, 0.999891, 0.999794, 0.999647, 0.999425, 0.999062, 0.997049, 0.995778,
+ 0.994652, 0.992778, 0.990482, 0.988004, 0.984893, 0.980881, 0.976605, 0.971199, 0.965610,
+ 0.958925, 0.951746, 0.943791, 0.935200, 0.926018, 0.916028, 0.905724, 0.894528, 0.882914,
+ 0.870740, 0.857802, 0.844552, 0.830857, 0.816921, 0.803102, 0.789625, 0.777480, 0.765891,
+ 0.753908, 0.741795, 0.729390, 0.716440, 0.703411, 0.690068, 0.676438, 0.662586, 0.648697,
+ 0.634732, 0.620997, 0.607451, 0.593765, 0.579748, 0.565661, 0.551594, 0.537396, 0.523433,
+ 0.509708, 0.495972, 0.482082, 0.468427, 0.454890, 0.441623, 1.000000, 1.000000, 0.999999,
+ 0.999991, 0.999977, 0.999940, 0.999875, 0.999769, 0.999605, 0.999352, 0.998882, 0.996665,
+ 0.995459, 0.994380, 0.992014, 0.989912, 0.986796, 0.983537, 0.979326, 0.974792, 0.969140,
+ 0.963160, 0.956222, 0.948807, 0.940518, 0.931755, 0.922452, 0.912319, 0.902227, 0.891142,
+ 0.879838, 0.868047, 0.855745, 0.842718, 0.829827, 0.816398, 0.802786, 0.789396, 0.776581,
+ 0.764901, 0.753710, 0.742102, 0.730448, 0.718337, 0.705768, 0.693172, 0.680153, 0.666882,
+ 0.653401, 0.639837, 0.626152, 0.612676, 0.599435, 0.586109, 0.572473, 0.558715, 0.544964,
+ 0.531112, 0.517416, 0.503992, 0.490653, 0.477162, 0.463832, 0.450645, 1.000000, 1.000000,
+ 0.999999, 0.999992, 0.999973, 0.999933, 0.999861, 0.999741, 0.999554, 0.999267, 0.998411,
+ 0.996303, 0.995191, 0.993945, 0.991406, 0.989019, 0.985720, 0.982057, 0.977501, 0.972605,
+ 0.966697, 0.960340, 0.953031, 0.945347, 0.936866, 0.927917, 0.918562, 0.908598, 0.898486,
+ 0.887794, 0.876545, 0.865379, 0.853428, 0.841167, 0.828649, 0.815967, 0.802957, 0.789865,
+ 0.777077, 0.764695, 0.753544, 0.742694, 0.731571, 0.720304, 0.708490, 0.696351, 0.684134,
+ 0.671470, 0.658541, 0.645376, 0.632209, 0.618776, 0.605511, 0.592527, 0.579546, 0.566310,
+ 0.552860, 0.539492, 0.526005, 0.512564, 0.499340, 0.486360, 0.473357, 0.460306, 1.000000,
+ 1.000000, 0.999998, 0.999991, 0.999970, 0.999926, 0.999842, 0.999710, 0.999498, 0.999164,
+ 0.997464, 0.995870, 0.994917, 0.992911, 0.990682, 0.987816, 0.984410, 0.980551, 0.975693,
+ 0.970263, 0.963946, 0.957248, 0.949765, 0.941571, 0.932941, 0.923873, 0.914332, 0.904560,
+ 0.894394, 0.884127, 0.873294, 0.862503, 0.851335, 0.839566, 0.827776, 0.815708, 0.803370,
+ 0.790821, 0.778386, 0.766121, 0.754193, 0.743420, 0.732975, 0.722326, 0.711376, 0.699992,
+ 0.688180, 0.676354, 0.664004, 0.651449, 0.638600, 0.625776, 0.612660, 0.599603, 0.586719,
+ 0.574078, 0.561273, 0.548129, 0.535155, 0.522015, 0.508851, 0.495837, 0.483190, 0.470624,
+ 1.000000, 1.000000, 0.999998, 0.999988, 0.999965, 0.999916, 0.999823, 0.999669, 0.999425,
+ 0.999025, 0.996874, 0.995670, 0.994415, 0.991991, 0.989766, 0.986646, 0.982812, 0.978356,
+ 0.973317, 0.967612, 0.960820, 0.953603, 0.945969, 0.937323, 0.928661, 0.919507, 0.909833,
+ 0.900245, 0.890390, 0.880252, 0.870000, 0.859518, 0.849163, 0.838101, 0.826960, 0.815688,
+ 0.804126, 0.792234, 0.780356, 0.768474, 0.756678, 0.745159, 0.734601, 0.724624, 0.714339,
+ 0.703751, 0.692766, 0.681267, 0.669799, 0.657871, 0.645577, 0.633102, 0.620560, 0.607737,
+ 0.594890, 0.582143, 0.569779, 0.557360, 0.544651, 0.531942, 0.519228, 0.506467, 0.493710,
+ 0.481143, 1.000000, 1.000000, 0.999998, 0.999988, 0.999961, 0.999902, 0.999798, 0.999622,
+ 0.999341, 0.998801, 0.996397, 0.995225, 0.993927, 0.991338, 0.988500, 0.985327, 0.981195,
+ 0.976383, 0.970726, 0.964471, 0.957386, 0.949813, 0.941694, 0.932681, 0.923974, 0.914755,
+ 0.905026, 0.895649, 0.886178, 0.876277, 0.866629, 0.856890, 0.846934, 0.836887, 0.826373,
+ 0.815885, 0.805169, 0.794133, 0.782812, 0.771547, 0.760175, 0.748896, 0.737687, 0.727152,
+ 0.717601, 0.707670, 0.697425, 0.686788, 0.675664, 0.664513, 0.652962, 0.640965, 0.628851,
+ 0.616551, 0.604168, 0.591559, 0.579009, 0.566648, 0.554597, 0.542382, 0.529999, 0.517655,
+ 0.505254, 0.492894, 1.000000, 1.000000, 0.999997, 0.999986, 0.999956, 0.999889, 0.999766,
+ 0.999562, 0.999240, 0.997952, 0.996094, 0.994979, 0.992773, 0.990536, 0.987214, 0.983322,
+ 0.978938, 0.973714, 0.967681, 0.960981, 0.953144, 0.945475, 0.936909, 0.927734, 0.918826,
+ 0.909590, 0.900085, 0.890867, 0.881801, 0.872565, 0.863236, 0.854239, 0.845060, 0.835686,
+ 0.826251, 0.816284, 0.806586, 0.796419, 0.785914, 0.775210, 0.764461, 0.753599, 0.742805,
+ 0.731872, 0.721370, 0.711898, 0.702337, 0.692383, 0.682137, 0.671365, 0.660479, 0.649314,
+ 0.637685, 0.625899, 0.613898, 0.601865, 0.589582, 0.577285, 0.565013, 0.553106, 0.541280,
+ 0.529367, 0.517320, 0.505411, 1.000000, 1.000000, 0.999997, 0.999983, 0.999948, 0.999869,
+ 0.999732, 0.999499, 0.999111, 0.997167, 0.995720, 0.994349, 0.991727, 0.989197, 0.985883,
+ 0.981483, 0.976618, 0.970597, 0.964122, 0.956994, 0.948639, 0.940500, 0.931606, 0.922385,
+ 0.913291, 0.904205, 0.894938, 0.885890, 0.877334, 0.868754, 0.860053, 0.851683, 0.843447,
+ 0.834889, 0.826304, 0.817441, 0.808285, 0.799141, 0.789570, 0.779600, 0.769510, 0.759155,
+ 0.748882, 0.738346, 0.727629, 0.717273, 0.707467, 0.698283, 0.688609, 0.678748, 0.668371,
+ 0.657739, 0.646951, 0.635765, 0.624254, 0.612647, 0.600900, 0.589061, 0.576998, 0.564991,
+ 0.553102, 0.541517, 0.530027, 0.518495, 1.000000, 1.000000, 0.999997, 0.999983, 0.999939,
+ 0.999851, 0.999684, 0.999412, 0.998925, 0.996597, 0.995207, 0.993603, 0.990903, 0.987594,
+ 0.983814, 0.979016, 0.973647, 0.967048, 0.960109, 0.952123, 0.943560, 0.934900, 0.925747,
+ 0.916566, 0.907305, 0.898441, 0.889629, 0.881042, 0.872874, 0.865064, 0.857225, 0.849446,
+ 0.842063, 0.834561, 0.826814, 0.818875, 0.810748, 0.802316, 0.793699, 0.784704, 0.775198,
+ 0.765643, 0.755735, 0.745873, 0.735526, 0.725229, 0.714892, 0.704807, 0.695502, 0.686241,
+ 0.676633, 0.666688, 0.656384, 0.645871, 0.635174, 0.624113, 0.612788, 0.601426, 0.589925,
+ 0.578399, 0.566612, 0.554931, 0.543383, 0.532065, 1.000000, 1.000000, 0.999996, 0.999977,
+ 0.999928, 0.999824, 0.999633, 0.999306, 0.998429, 0.996133, 0.994890, 0.992316, 0.989752,
+ 0.986095, 0.981564, 0.976234, 0.970081, 0.962779, 0.955232, 0.946702, 0.937716, 0.928604,
+ 0.919281, 0.910167, 0.901046, 0.892446, 0.884183, 0.876253, 0.868619, 0.861545, 0.854673,
+ 0.847885, 0.841074, 0.834610, 0.827984, 0.820945, 0.813648, 0.806232, 0.798444, 0.790232,
+ 0.781853, 0.772897, 0.763648, 0.754227, 0.744542, 0.734689, 0.724526, 0.714204, 0.704152,
+ 0.694222, 0.685143, 0.675860, 0.666319, 0.656415, 0.646273, 0.635902, 0.625399, 0.614563,
+ 0.603490, 0.592413, 0.581217, 0.570000, 0.558608, 0.547242, 1.000000, 0.999999, 0.999995,
+ 0.999972, 0.999915, 0.999790, 0.999562, 0.999168, 0.997237, 0.995672, 0.994074, 0.991220,
+ 0.987792, 0.983822, 0.978599, 0.972804, 0.965718, 0.958053, 0.949460, 0.940503, 0.931011,
+ 0.921608, 0.912409, 0.903378, 0.894606, 0.886369, 0.878756, 0.871573, 0.864862, 0.858421,
+ 0.852541, 0.846802, 0.841027, 0.835206, 0.829628, 0.823730, 0.817415, 0.810655, 0.803873,
+ 0.796659, 0.788887, 0.780940, 0.772537, 0.763507, 0.754487, 0.745163, 0.735572, 0.725687,
+ 0.715611, 0.705398, 0.695418, 0.685592, 0.676518, 0.667304, 0.657875, 0.648182, 0.638235,
+ 0.628062, 0.617813, 0.607283, 0.596552, 0.585770, 0.575033, 0.564153, 1.000000, 1.000000,
+ 0.999995, 0.999970, 0.999898, 0.999748, 0.999472, 0.998969, 0.996528, 0.995102, 0.992701,
+ 0.989963, 0.985981, 0.981194, 0.975183, 0.968501, 0.960502, 0.952012, 0.942861, 0.933376,
+ 0.923506, 0.914042, 0.904921, 0.896282, 0.887987, 0.880341, 0.873536, 0.867293, 0.861556,
+ 0.856148, 0.850987, 0.846352, 0.841684, 0.836880, 0.832036, 0.827091, 0.821900, 0.816206,
+ 0.810042, 0.803629, 0.796918, 0.789653, 0.781915, 0.774014, 0.765530, 0.756526, 0.747669,
+ 0.738342, 0.728770, 0.718942, 0.708942, 0.698855, 0.688933, 0.679131, 0.669855, 0.660811,
+ 0.651549, 0.642127, 0.632454, 0.622651, 0.612709, 0.602606, 0.592344, 0.581877, 1.000000,
+ 0.999999, 0.999993, 0.999963, 0.999874, 0.999691, 0.999350, 0.998431, 0.995873, 0.994456,
+ 0.991327, 0.987798, 0.983232, 0.977500, 0.970828, 0.962815, 0.954228, 0.944752, 0.935126,
+ 0.925179, 0.915102, 0.905763, 0.897087, 0.888933, 0.881452, 0.874687, 0.868716, 0.863585,
+ 0.858931, 0.854662, 0.850569, 0.846719, 0.843151, 0.839426, 0.835588, 0.831443, 0.827004,
+ 0.822395, 0.817254, 0.811630, 0.805464, 0.799124, 0.792382, 0.785091, 0.777315, 0.769360,
+ 0.760908, 0.751957, 0.743128, 0.733917, 0.724340, 0.714713, 0.704721, 0.694835, 0.684862,
+ 0.675099, 0.665570, 0.656644, 0.647651, 0.638581, 0.629337, 0.619926, 0.610358, 0.600707,
+ 1.000000, 1.000000, 0.999990, 0.999953, 0.999843, 0.999613, 0.999186, 0.997025, 0.995317,
+ 0.992850, 0.989760, 0.985270, 0.979807, 0.973049, 0.965228, 0.956248, 0.946394, 0.936324,
+ 0.926124, 0.915808, 0.905942, 0.897060, 0.889001, 0.881755, 0.875351, 0.869688, 0.864736,
+ 0.860745, 0.857305, 0.854190, 0.851261, 0.848484, 0.845642, 0.842948, 0.840060, 0.836901,
+ 0.833379, 0.829393, 0.825103, 0.820431, 0.815288, 0.809575, 0.803326, 0.796949, 0.790174,
+ 0.782873, 0.775048, 0.767139, 0.758772, 0.750019, 0.741120, 0.732127, 0.722743, 0.713225,
+ 0.703637, 0.693768, 0.684016, 0.674277, 0.664703, 0.655328, 0.646550, 0.637812, 0.629036,
+ 0.620129, 1.000000, 1.000000, 0.999988, 0.999933, 0.999800, 0.999508, 0.998917, 0.996236,
+ 0.994617, 0.991176, 0.987089, 0.981880, 0.974966, 0.967156, 0.957914, 0.947585, 0.936937,
+ 0.926318, 0.915662, 0.905567, 0.896223, 0.888166, 0.881117, 0.875079, 0.869981, 0.865675,
+ 0.862091, 0.859183, 0.856981, 0.855065, 0.853273, 0.851572, 0.849782, 0.847768, 0.845668,
+ 0.843345, 0.840703, 0.837646, 0.834094, 0.830030, 0.825631, 0.820873, 0.815619, 0.809856,
+ 0.803578, 0.797096, 0.790359, 0.783152, 0.775507, 0.767504, 0.759411, 0.750982, 0.742208,
+ 0.733383, 0.724445, 0.715190, 0.705827, 0.696440, 0.686773, 0.677242, 0.667735, 0.658471,
+ 0.649236, 0.640305, 1.000000, 0.999999, 0.999984, 0.999918, 0.999737, 0.999350, 0.997576,
+ 0.995476, 0.992614, 0.988817, 0.983601, 0.976880, 0.968694, 0.959092, 0.948297, 0.936831,
+ 0.925592, 0.914494, 0.904159, 0.894643, 0.886417, 0.879620, 0.874023, 0.869533, 0.865967,
+ 0.863238, 0.861113, 0.859527, 0.858367, 0.857594, 0.856882, 0.856172, 0.855316, 0.854197,
+ 0.852818, 0.851062, 0.849046, 0.846747, 0.844043, 0.840842, 0.837164, 0.832985, 0.828344,
+ 0.823544, 0.818276, 0.812543, 0.806374, 0.799838, 0.793170, 0.786246, 0.778956, 0.771297,
+ 0.763278, 0.755252, 0.746984, 0.738445, 0.729688, 0.721045, 0.712189, 0.703099, 0.694045,
+ 0.684930, 0.675601, 0.666480, 1.000000, 0.999999, 0.999978, 0.999888, 0.999639, 0.999093,
+ 0.996310, 0.994405, 0.990527, 0.985186, 0.978518, 0.969748, 0.959597, 0.948104, 0.935724,
+ 0.923704, 0.912023, 0.901356, 0.891850, 0.883847, 0.877280, 0.872289, 0.868583, 0.865913,
+ 0.864098, 0.862993, 0.862356, 0.862125, 0.862107, 0.862168, 0.862359, 0.862490, 0.862430,
+ 0.862063, 0.861431, 0.860386, 0.858950, 0.857090, 0.854848, 0.852381, 0.849503, 0.846167,
+ 0.842399, 0.838194, 0.833566, 0.828579, 0.823464, 0.817951, 0.812079, 0.805873, 0.799320,
+ 0.792533, 0.785715, 0.778636, 0.771260, 0.763618, 0.755719, 0.747815, 0.739825, 0.731602,
+ 0.723212, 0.714845, 0.706465, 0.697933, 1.000000, 0.999998, 0.999969, 0.999836, 0.999475,
+ 0.997943, 0.995219, 0.991760, 0.986663, 0.979592, 0.970218, 0.959155, 0.946575, 0.933047,
+ 0.920022, 0.907749, 0.896801, 0.887506, 0.880077, 0.874322, 0.870126, 0.867481, 0.865949,
+ 0.865293, 0.865287, 0.865746, 0.866502, 0.867439, 0.868442, 0.869382, 0.870161, 0.870782,
+ 0.871303, 0.871511, 0.871427, 0.870978, 0.870136, 0.868892, 0.867248, 0.865209, 0.862775,
+ 0.859944, 0.857004, 0.853671, 0.849984, 0.845927, 0.841518, 0.836774, 0.831750, 0.826407,
+ 0.821001, 0.815333, 0.809412, 0.803238, 0.796802, 0.790204, 0.783457, 0.776713, 0.769749,
+ 0.762596, 0.755239, 0.747690, 0.740127, 0.732595, 1.000000, 0.999997, 0.999950, 0.999744,
+ 0.999162, 0.996124, 0.992844, 0.987757, 0.980062, 0.969642, 0.957087, 0.942735, 0.927747,
+ 0.913622, 0.900889, 0.890115, 0.881584, 0.875288, 0.870926, 0.868307, 0.867033, 0.866972,
+ 0.867692, 0.868950, 0.870549, 0.872320, 0.874144, 0.875947, 0.877674, 0.879192, 0.880478,
+ 0.881539, 0.882307, 0.882739, 0.882902, 0.882847, 0.882461, 0.881725, 0.880636, 0.879197,
+ 0.877422, 0.875296, 0.872849, 0.870076, 0.866988, 0.863637, 0.860159, 0.856475, 0.852525,
+ 0.848328, 0.843883, 0.839198, 0.834322, 0.829221, 0.823907, 0.818461, 0.812972, 0.807316,
+ 0.801474, 0.795459, 0.789276, 0.783025, 0.776615, 0.770223, 0.999999, 0.999994, 0.999909,
+ 0.999536, 0.997195, 0.994123, 0.988168, 0.979344, 0.967003, 0.951763, 0.934724, 0.917948,
+ 0.902918, 0.890432, 0.880902, 0.874401, 0.870394, 0.868503, 0.868209, 0.869062, 0.870725,
+ 0.873006, 0.875558, 0.878230, 0.880893, 0.883445, 0.885832, 0.888059, 0.890058, 0.891782,
+ 0.893247, 0.894460, 0.895397, 0.896023, 0.896380, 0.896433, 0.896198, 0.895673, 0.894865,
+ 0.893908, 0.892700, 0.891224, 0.889501, 0.887539, 0.885336, 0.882903, 0.880244, 0.877373,
+ 0.874296, 0.871019, 0.867549, 0.863933, 0.860153, 0.856355, 0.852395, 0.848277, 0.844006,
+ 0.839587, 0.835045, 0.830378, 0.825579, 0.820649, 0.815592, 0.810432, 0.999998, 0.999988,
+ 0.999795, 0.998892, 0.994635, 0.987290, 0.975397, 0.958508, 0.938352, 0.917733, 0.899800,
+ 0.885878, 0.876516, 0.871200, 0.869099, 0.869317, 0.871112, 0.873870, 0.877160, 0.880682,
+ 0.884228, 0.887737, 0.891076, 0.894161, 0.896981, 0.899543, 0.901847, 0.903882, 0.905672,
+ 0.907188, 0.908451, 0.909480, 0.910289, 0.910878, 0.911259, 0.911430, 0.911396, 0.911154,
+ 0.910712, 0.910081, 0.909266, 0.908264, 0.907094, 0.905752, 0.904244, 0.902577, 0.900799,
+ 0.898931, 0.896923, 0.894782, 0.892513, 0.890117, 0.887600, 0.884968, 0.882222, 0.879369,
+ 0.876408, 0.873345, 0.870183, 0.866926, 0.863575, 0.860160, 0.856672, 0.853098, 0.999991,
+ 0.999947, 0.999158, 0.992842, 0.980107, 0.957230, 0.928231, 0.901539, 0.882688, 0.872588,
+ 0.869394, 0.870671, 0.874458, 0.879378, 0.884639, 0.889770, 0.894601, 0.898972, 0.902930,
+ 0.906456, 0.909568, 0.912329, 0.914750, 0.916893, 0.918774, 0.920429, 0.921868, 0.923110,
+ 0.924185, 0.925089, 0.925842, 0.926457, 0.926934, 0.927285, 0.927522, 0.927639, 0.927650,
+ 0.927553, 0.927356, 0.927061, 0.926671, 0.926187, 0.925617, 0.924962, 0.924224, 0.923409,
+ 0.922519, 0.921555, 0.920521, 0.919419, 0.918252, 0.917021, 0.915729, 0.914377, 0.912967,
+ 0.911503, 0.909984, 0.908414, 0.906791, 0.905122, 0.903401, 0.901637, 0.899826, 0.897972,
+ 0.987461, 0.940121, 0.871507, 0.898572, 0.916705, 0.926425, 0.931922, 0.935265, 0.937431,
+ 0.938899, 0.939950, 0.940717, 0.941301, 0.941754, 0.942111, 0.942397, 0.942631, 0.942823,
+ 0.942983, 0.943117, 0.943231, 0.943329, 0.943412, 0.943484, 0.943545, 0.943599, 0.943644,
+ 0.943682, 0.943716, 0.943744, 0.943766, 0.943785, 0.943799, 0.943808, 0.943815, 0.943818,
+ 0.943818, 0.943814, 0.943807, 0.943797, 0.943784, 0.943769, 0.943751, 0.943730, 0.943707,
+ 0.943681, 0.943652, 0.943623, 0.943589, 0.943554, 0.943518, 0.943479, 0.943438, 0.943396,
+ 0.943351, 0.943305, 0.943257, 0.943207, 0.943156, 0.943104, 0.943049, 0.942993, 0.942936,
+ 0.942877,
+};
+
+#endif /* __EEVEE_LUT_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
new file mode 100644
index 00000000000..401b39fbd3e
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file eevee_private.h
+ * \ingroup DNA
+ */
+
+struct Object;
+
+/* keep it under MAX_PASSES */
+typedef struct EEVEE_PassList {
+ struct DRWPass *depth_pass;
+ struct DRWPass *depth_pass_cull;
+ struct DRWPass *pass;
+ struct DRWPass *tonemap;
+} EEVEE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EEVEE_FramebufferList {
+ struct GPUFrameBuffer *main; /* HDR */
+} EEVEE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EEVEE_TextureList {
+ struct GPUTexture *color; /* R11_G11_B10 */
+} EEVEE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EEVEE_StorageList {
+ /* Lights */
+ struct EEVEE_LightsInfo *lights_info; /* Number of lights, ... */
+ struct EEVEE_Light *lights_data; /* Array, Packed lights data info, duplication of what is in the Uniform Buffer in Vram */
+ struct Object **lights_ref; /* List of all lights in the buffer. */
+ struct GPUUniformBuffer *lights_ubo;
+ struct g_data *g_data;
+} EEVEE_StorageList;
+
+typedef struct EEVEE_LightsInfo {
+ int light_count;
+} EEVEE_LightsInfo;
+
+typedef struct EEVEE_Data {
+ void *engine_type;
+ EEVEE_FramebufferList *fbl;
+ EEVEE_TextureList *txl;
+ EEVEE_PassList *psl;
+ EEVEE_StorageList *stl;
+} EEVEE_Data;
+
+typedef struct g_data{
+ struct DRWShadingGroup *default_lit_grp;
+ struct DRWShadingGroup *depth_shgrp;
+ struct DRWShadingGroup *depth_shgrp_select;
+ struct DRWShadingGroup *depth_shgrp_active;
+ struct DRWShadingGroup *depth_shgrp_cull;
+ struct DRWShadingGroup *depth_shgrp_cull_select;
+ struct DRWShadingGroup *depth_shgrp_cull_active;
+
+ struct ListBase lamps; /* Lamps gathered during cache iteration */
+} g_data; /* Transient data */
+
+/* eevee_lights.c */
+void EEVEE_lights_init(EEVEE_StorageList *stl);
+void EEVEE_lights_cache_init(EEVEE_StorageList *stl);
+void EEVEE_lights_cache_add(EEVEE_StorageList *stl, struct Object *ob);
+void EEVEE_lights_cache_finish(EEVEE_StorageList *stl);
+void EEVEE_lights_update(EEVEE_StorageList *stl);
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
new file mode 100644
index 00000000000..3a91e284184
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -0,0 +1,197 @@
+
+#define M_PI 3.14159265358979323846 /* pi */
+#define M_1_PI 0.318309886183790671538 /* 1/pi */
+#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
+#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
+
+/* ------- Structures -------- */
+
+struct LightData {
+ vec4 position_influence; /* w : InfluenceRadius */
+ vec4 color_spec; /* w : Spec Intensity */
+ vec4 spotdata_shadow; /* x : spot size, y : spot blend */
+ vec4 rightvec_sizex; /* xyz: Normalized up vector, w: Lamp Type */
+ vec4 upvec_sizey; /* xyz: Normalized right vector, w: Lamp Type */
+ vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */
+};
+
+/* convenience aliases */
+#define l_color color_spec.rgb
+#define l_spec color_spec.a
+#define l_position position_influence.xyz
+#define l_influence position_influence.w
+#define l_sizex rightvec_sizex.w
+#define l_radius rightvec_sizex.w
+#define l_sizey upvec_sizey.w
+#define l_right rightvec_sizex.xyz
+#define l_up upvec_sizey.xyz
+#define l_forward forwardvec_type.xyz
+#define l_type forwardvec_type.w
+#define l_spot_size spotdata_shadow.x
+#define l_spot_blend spotdata_shadow.y
+
+struct AreaData {
+ vec3 corner[4];
+ float solid_angle;
+};
+
+struct ShadingData {
+ vec3 V; /* View vector */
+ vec3 N; /* World Normal of the fragment */
+ vec3 W; /* World Position of the fragment */
+ vec3 R; /* Reflection vector */
+ vec3 L; /* Current Light vector (normalized) */
+ vec3 spec_dominant_dir; /* dominant direction of the specular rays */
+ vec3 l_vector; /* Current Light vector */
+ float l_distance; /* distance(l_position, W) */
+ AreaData area_data; /* If current light is an area light */
+};
+
+/* ------- Convenience functions --------- */
+
+vec3 mul(mat3 m, vec3 v) { return m * v; }
+mat3 mul(mat3 m1, mat3 m2) { return m1 * m2; }
+
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return vec2(saturate(a.x), saturate(a.y)); }
+vec3 saturate(vec3 a) { return vec3(saturate(a.x), saturate(a.y), saturate(a.z)); }
+vec4 saturate(vec4 a) { return vec4(saturate(a.x), saturate(a.y), saturate(a.z), saturate(a.w)); }
+
+float distance_squared(vec2 a, vec2 b) { a -= b; return dot(a, a); }
+float distance_squared(vec3 a, vec3 b) { a -= b; return dot(a, a); }
+
+float hypot(float x, float y) { return sqrt(x*x + y*y); }
+
+float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); }
+
+float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
+{
+ return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
+}
+
+vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
+{
+ float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);
+ return lineorigin + linedirection * dist;
+}
+
+float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
+{
+ /* aligned plane normal */
+ vec3 L = planeorigin - lineorigin;
+ float diskdist = length(L);
+ vec3 planenormal = -normalize(L);
+ return -diskdist / dot(planenormal, linedirection);
+}
+
+vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
+{
+ float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin);
+ if (dist < 0) {
+ /* if intersection is behind we fake the intersection to be
+ * really far and (hopefully) not inside the radius of interest */
+ dist = 1e16;
+ }
+ return lineorigin + linedirection * dist;
+}
+
+float rectangle_solid_angle(AreaData ad)
+{
+ vec3 n0 = normalize(cross(ad.corner[0], ad.corner[1]));
+ vec3 n1 = normalize(cross(ad.corner[1], ad.corner[2]));
+ vec3 n2 = normalize(cross(ad.corner[2], ad.corner[3]));
+ vec3 n3 = normalize(cross(ad.corner[3], ad.corner[0]));
+
+ float g0 = acos(dot(-n0, n1));
+ float g1 = acos(dot(-n1, n2));
+ float g2 = acos(dot(-n2, n3));
+ float g3 = acos(dot(-n3, n0));
+
+ return max(0.0, (g0 + g1 + g2 + g3 - 2.0 * M_PI));
+}
+
+vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness)
+{
+ return normalize(mix(N, R, 1.0 - roughness * roughness));
+}
+
+/* From UE4 paper */
+vec3 mrp_sphere(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out float energy_conservation)
+{
+ roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */
+
+ /* energy preservation */
+ float sphere_angle = saturate(ld.l_radius / sd.l_distance);
+ energy_conservation = pow(roughness / saturate(roughness + 0.5 * sphere_angle), 2.0);
+
+ /* sphere light */
+ float inter_dist = dot(sd.l_vector, dir);
+ vec3 closest_point_on_ray = inter_dist * dir;
+ vec3 center_to_ray = closest_point_on_ray - sd.l_vector;
+
+ /* closest point on sphere */
+ vec3 closest_point_on_sphere = sd.l_vector + center_to_ray * saturate(ld.l_radius * inverse_distance(center_to_ray));
+
+ return normalize(closest_point_on_sphere);
+}
+
+vec3 mrp_area(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out float energy_conservation)
+{
+ roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */
+
+ /* FIXME : This needs to be fixed */
+ energy_conservation = pow(roughness / saturate(roughness + 0.5 * sd.area_data.solid_angle), 2.0);
+
+ vec3 refproj = line_plane_intersect(sd.W, dir, ld.l_position, ld.l_forward);
+
+ /* Project the point onto the light plane */
+ vec3 refdir = refproj - ld.l_position;
+ vec2 mrp = vec2(dot(refdir, ld.l_right), dot(refdir, ld.l_up));
+
+ /* clamp to light shape bounds */
+ vec2 area_half_size = vec2(ld.l_sizex, ld.l_sizey);
+ mrp = clamp(mrp, -area_half_size, area_half_size);
+
+ /* go back in world space */
+ vec3 closest_point_on_rectangle = sd.l_vector + mrp.x * ld.l_right + mrp.y * ld.l_up;
+
+ float len = length(closest_point_on_rectangle);
+ energy_conservation /= len * len;
+
+ return closest_point_on_rectangle / len;
+}
+
+/* GGX */
+float D_ggx_opti(float NH, float a2)
+{
+ float tmp = (NH * a2 - NH) * NH + 1.0;
+ return M_PI * tmp*tmp; /* Doing RCP and mul a2 at the end */
+}
+
+float G1_Smith_GGX(float NX, float a2)
+{
+ /* Using Brian Karis approach and refactoring by NX/NX
+ * this way the (2*NL)*(2*NV) in G = G1(V) * G1(L) gets canceled by the brdf denominator 4*NL*NV
+ * Rcp is done on the whole G later
+ * Note that this is not convenient for the transmition formula */
+ return NX + sqrt(NX * (NX - NX * a2) + a2);
+ /* return 2 / (1 + sqrt(1 + a2 * (1 - NX*NX) / (NX*NX) ) ); /* Reference function */
+}
+
+float bsdf_ggx(vec3 N, vec3 L, vec3 V, float roughness)
+{
+ float a = roughness;
+ float a2 = a * a;
+
+ vec3 H = normalize(L + V);
+ float NH = max(dot(N, H), 1e-8);
+ float NL = max(dot(N, L), 1e-8);
+ float NV = max(dot(N, V), 1e-8);
+
+ float G = G1_Smith_GGX(NV, a2) * G1_Smith_GGX(NL, a2); /* Doing RCP at the end */
+ float D = D_ggx_opti(NH, a2);
+
+ /* Denominator is canceled by G1_Smith */
+ /* bsdf = D * G / (4.0 * NL * NV); /* Reference function */
+ return NL * a2 / (D * G); /* NL to Fit cycles Equation : line. 345 in bsdf_microfacet.h */
+}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
new file mode 100644
index 00000000000..afa87dfb2c8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
@@ -0,0 +1,173 @@
+/* Bsdf direct light function */
+/* in other word, how materials react to scene lamps */
+
+/* Naming convention
+ * V View vector (normalized)
+ * N World Normal (normalized)
+ * L Outgoing Light Vector (Surface to Light in World Space) (normalized)
+ * Ldist Distance from surface to the light
+ * W World Pos
+ */
+
+/* ------------ Diffuse ------------- */
+
+float direct_diffuse_point(LightData ld, ShadingData sd)
+{
+ float bsdf = max(0.0, dot(sd.N, sd.L));
+ bsdf /= sd.l_distance * sd.l_distance;
+ return bsdf;
+}
+
+/* From Frostbite PBR Course
+ * Analitical irradiance from a sphere with correct horizon handling
+ * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
+float direct_diffuse_sphere(LightData ld, ShadingData sd)
+{
+ float radius = max(ld.l_sizex, 0.0001);
+ float costheta = clamp(dot(sd.N, sd.L), -0.999, 0.999);
+ float h = min(ld.l_radius / sd.l_distance , 0.9999);
+ float h2 = h*h;
+ float costheta2 = costheta * costheta;
+ float bsdf;
+
+ if (costheta2 > h2) {
+ bsdf = M_PI * h2 * clamp(costheta, 0.0, 1.0);
+ }
+ else {
+ float sintheta = sqrt(1.0 - costheta2);
+ float x = sqrt(1.0 / h2 - 1.0);
+ float y = -x * (costheta / sintheta);
+ float sinthetasqrty = sintheta * sqrt(1.0 - y * y);
+ bsdf = (costheta * acos(y) - x * sinthetasqrty) * h2 + atan(sinthetasqrty / x);
+ }
+
+ bsdf = max(bsdf, 0.0);
+ bsdf *= M_1_PI2;
+
+ return bsdf;
+}
+
+/* From Frostbite PBR Course
+ * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
+float direct_diffuse_rectangle(LightData ld, ShadingData sd)
+{
+#ifdef USE_LTC
+ float bsdf = ltc_evaluate(sd.N, sd.V, mat3(1.0), sd.area_data.corner);
+ bsdf *= M_1_2PI;
+#else
+ float bsdf = sd.area_data.solid_angle * 0.2 * (
+ max(0.0, dot(normalize(sd.area_data.corner[0]), sd.N)) +
+ max(0.0, dot(normalize(sd.area_data.corner[1]), sd.N)) +
+ max(0.0, dot(normalize(sd.area_data.corner[2]), sd.N)) +
+ max(0.0, dot(normalize(sd.area_data.corner[3]), sd.N)) +
+ max(0.0, dot(sd.L, sd.N))
+ );
+ bsdf *= M_1_PI;
+#endif
+ return bsdf;
+}
+
+/* infinitly far away point source, no decay */
+float direct_diffuse_sun(LightData ld, ShadingData sd)
+{
+ float bsdf = max(0.0, dot(sd.N, sd.L));
+ bsdf *= M_1_PI; /* Normalize */
+ return bsdf;
+}
+
+#if 0
+float direct_diffuse_unit_disc(vec3 N, vec3 L)
+{
+
+}
+#endif
+
+/* ----------- GGx ------------ */
+float direct_ggx_point(ShadingData sd, float roughness)
+{
+ float bsdf = bsdf_ggx(sd.N, sd.L, sd.V, roughness);
+ bsdf /= sd.l_distance * sd.l_distance;
+ return bsdf;
+}
+
+float direct_ggx_sphere(LightData ld, ShadingData sd, float roughness)
+{
+#ifdef USE_LTC
+ vec3 P = line_aligned_plane_intersect(vec3(0.0), sd.spec_dominant_dir, sd.l_vector);
+
+ vec3 Px = normalize(P - sd.l_vector) * ld.l_radius;
+ vec3 Py = cross(Px, sd.L);
+
+ float NV = max(dot(sd.N, sd.V), 1e-8);
+ vec2 uv = ltc_coords(NV, sqrt(roughness));
+ mat3 ltcmat = ltc_matrix(uv);
+
+// #define HIGHEST_QUALITY
+#ifdef HIGHEST_QUALITY
+ vec3 Pxy1 = normalize( Px + Py) * ld.l_radius;
+ vec3 Pxy2 = normalize(-Px + Py) * ld.l_radius;
+
+ /* counter clockwise */
+ vec3 points[8];
+ points[0] = sd.l_vector + Px;
+ points[1] = sd.l_vector - Pxy2;
+ points[2] = sd.l_vector - Py;
+ points[3] = sd.l_vector - Pxy1;
+ points[4] = sd.l_vector - Px;
+ points[5] = sd.l_vector + Pxy2;
+ points[6] = sd.l_vector + Py;
+ points[7] = sd.l_vector + Pxy1;
+ float bsdf = ltc_evaluate_circle(sd.N, sd.V, ltcmat, points);
+#else
+ vec3 points[4];
+ points[0] = sd.l_vector + Px;
+ points[1] = sd.l_vector - Py;
+ points[2] = sd.l_vector - Px;
+ points[3] = sd.l_vector + Py;
+ float bsdf = ltc_evaluate(sd.N, sd.V, ltcmat, points);
+ /* sqrt(pi/2) difference between square and disk area */
+ bsdf *= 1.25331413731;
+#endif
+
+ bsdf *= texture(ltcMag, uv).r; /* Bsdf intensity */
+ bsdf *= M_1_2PI * M_1_PI;
+#else
+ float energy_conservation;
+ vec3 L = mrp_sphere(ld, sd, sd.spec_dominant_dir, roughness, energy_conservation);
+ float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
+
+ bsdf *= energy_conservation / (sd.l_distance * sd.l_distance);
+ bsdf *= max(ld.l_radius * ld.l_radius, 1e-16); /* radius is already inside energy_conservation */
+#endif
+ return bsdf;
+}
+
+float direct_ggx_rectangle(LightData ld, ShadingData sd, float roughness)
+{
+#ifdef USE_LTC
+ float NV = max(dot(sd.N, sd.V), 1e-8);
+ vec2 uv = ltc_coords(NV, sqrt(roughness));
+ mat3 ltcmat = ltc_matrix(uv);
+
+ float bsdf = ltc_evaluate(sd.N, sd.V, ltcmat, sd.area_data.corner);
+ bsdf *= texture(ltcMag, uv).r; /* Bsdf intensity */
+ bsdf *= M_1_2PI;
+#else
+ float energy_conservation;
+ vec3 L = mrp_area(ld, sd, sd.spec_dominant_dir, roughness, energy_conservation);
+ float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
+
+ bsdf *= energy_conservation;
+ /* fade mrp artifacts */
+ bsdf *= max(0.0, dot(-sd.spec_dominant_dir, ld.l_forward));
+ bsdf *= max(0.0, -dot(L, ld.l_forward));
+#endif
+ return bsdf;
+}
+
+#if 0
+float direct_ggx_disc(vec3 N, vec3 L)
+{
+
+}
+#endif \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
new file mode 100644
index 00000000000..019f2d522f6
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -0,0 +1,133 @@
+
+uniform int light_count;
+uniform vec3 cameraPos;
+uniform vec3 eye;
+uniform mat4 ProjectionMatrix;
+
+
+layout(std140) uniform light_block {
+ LightData lights_data[MAX_LIGHT];
+};
+
+in vec3 worldPosition;
+in vec3 worldNormal;
+
+out vec4 fragColor;
+
+/* type */
+#define POINT 0.0
+#define SUN 1.0
+#define SPOT 2.0
+#define HEMI 3.0
+#define AREA 4.0
+
+float light_diffuse(LightData ld, ShadingData sd)
+{
+ if (ld.l_type == SUN) {
+ return direct_diffuse_sun(ld, sd);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_diffuse_rectangle(ld, sd);
+ }
+ else {
+ return direct_diffuse_sphere(ld, sd);
+ }
+}
+
+float light_specular(LightData ld, ShadingData sd, float roughness)
+{
+ if (ld.l_type == SUN) {
+ return direct_ggx_point(sd, roughness);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_ggx_rectangle(ld, sd, roughness);
+ }
+ else {
+ // return direct_ggx_point(sd, roughness);
+ return direct_ggx_sphere(ld, sd, roughness);
+ }
+}
+
+float light_visibility(LightData ld, ShadingData sd)
+{
+ float vis = 1.0;
+
+ if (ld.l_type == SPOT) {
+ float z = dot(ld.l_forward, sd.l_vector);
+ vec3 lL = sd.l_vector / z;
+ float x = dot(ld.l_right, lL) / ld.l_sizex;
+ float y = dot(ld.l_up, lL) / ld.l_sizey;
+
+ float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+
+ float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
+
+ vis *= spotmask;
+ }
+ else if (ld.l_type == AREA) {
+ vis *= step(0.0, -dot(sd.L, ld.l_forward));
+ }
+
+ return vis;
+}
+
+/* Calculation common to all bsdfs */
+float light_common(inout LightData ld, inout ShadingData sd)
+{
+ float vis = 1.0;
+
+ if (ld.l_type == SUN) {
+ sd.L = -ld.l_forward;
+ }
+ else {
+ sd.L = sd.l_vector / sd.l_distance;
+ }
+
+ if (ld.l_type == AREA) {
+ sd.area_data.corner[0] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
+ sd.area_data.corner[1] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
+ sd.area_data.corner[2] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
+ sd.area_data.corner[3] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+#ifndef USE_LTC
+ sd.area_data.solid_angle = rectangle_solid_angle(sd.area_data);
+#endif
+ }
+
+ return vis;
+}
+
+void main()
+{
+ ShadingData sd;
+ sd.N = normalize(worldNormal);
+ sd.V = (ProjectionMatrix[3][3] == 0.0) /* if perspective */
+ ? normalize(cameraPos - worldPosition)
+ : normalize(eye);
+ sd.W = worldPosition;
+ sd.R = reflect(-sd.V, sd.N);
+
+ /* hardcoded test vars */
+ vec3 albedo = vec3(0.0);
+ vec3 specular = mix(vec3(1.0), vec3(1.0), pow(max(0.0, 1.0 - dot(sd.N, sd.V)), 5.0));
+ float roughness = 0.1;
+
+ sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughness);
+
+ vec3 radiance = vec3(0.0);
+ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
+ LightData ld = lights_data[i];
+
+ sd.l_vector = ld.l_position - worldPosition;
+ sd.l_distance = length(sd.l_vector);
+
+ light_common(ld, sd);
+
+ float vis = light_visibility(ld, sd);
+ float spec = light_specular(ld, sd, roughness);
+ float diff = light_diffuse(ld, sd);
+
+ radiance += vis * (albedo * diff + specular * spec) * ld.l_color;
+ }
+
+ fragColor = vec4(radiance, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
new file mode 100644
index 00000000000..d0a5ee06694
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -0,0 +1,16 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+uniform mat3 WorldNormalMatrix;
+
+in vec3 pos;
+in vec3 nor;
+
+out vec3 worldPosition;
+out vec3 worldNormal;
+
+void main() {
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ worldPosition = (ModelMatrix * vec4(pos, 1.0)).xyz;
+ worldNormal = WorldNormalMatrix * nor;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
new file mode 100644
index 00000000000..131b0c2de78
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
@@ -0,0 +1,243 @@
+/* Mainly From https://eheitzresearch.wordpress.com/415-2/ */
+
+#define USE_LTC
+#define LTC_LUT_SIZE 64
+
+uniform sampler2D ltcMat;
+uniform sampler2D ltcMag;
+
+/* from Real-Time Area Lighting: a Journey from Research to Production
+ * Stephen Hill and Eric Heitz */
+float edge_integral(vec3 p1, vec3 p2)
+{
+#if 0
+ /* more accurate replacement of acos */
+ float x = dot(p1, p2);
+ float y = abs(x);
+
+ float a = 5.42031 + (3.12829 + 0.0902326 * y) * y;
+ float b = 3.45068 + (4.18814 + y) * y;
+ float theta_sintheta = a / b;
+
+ if (x < 0.0) {
+ theta_sintheta = (M_PI / sqrt(1.0 - x * x)) - theta_sintheta;
+ }
+ vec3 u = cross(p1, p2);
+ return theta_sintheta * dot(u, N);
+#endif
+ float cos_theta = dot(p1, p2);
+ cos_theta = clamp(cos_theta, -0.9999, 0.9999);
+
+ float theta = acos(cos_theta);
+ vec3 u = normalize(cross(p1, p2));
+ return theta * cross(p1, p2).z / sin(theta);
+}
+
+int clip_quad_to_horizon(inout vec3 L[5])
+{
+ /* detect clipping config */
+ int config = 0;
+ if (L[0].z > 0.0) config += 1;
+ if (L[1].z > 0.0) config += 2;
+ if (L[2].z > 0.0) config += 4;
+ if (L[3].z > 0.0) config += 8;
+
+ /* clip */
+ int n = 0;
+
+ if (config == 0)
+ {
+ /* clip all */
+ }
+ else if (config == 1) /* V1 clip V2 V3 V4 */
+ {
+ n = 3;
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ L[2] = -L[3].z * L[0] + L[0].z * L[3];
+ }
+ else if (config == 2) /* V2 clip V1 V3 V4 */
+ {
+ n = 3;
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ }
+ else if (config == 3) /* V1 V2 clip V3 V4 */
+ {
+ n = 4;
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ L[3] = -L[3].z * L[0] + L[0].z * L[3];
+ }
+ else if (config == 4) /* V3 clip V1 V2 V4 */
+ {
+ n = 3;
+ L[0] = -L[3].z * L[2] + L[2].z * L[3];
+ L[1] = -L[1].z * L[2] + L[2].z * L[1];
+ }
+ else if (config == 5) /* V1 V3 clip V2 V4) impossible */
+ {
+ n = 0;
+ }
+ else if (config == 6) /* V2 V3 clip V1 V4 */
+ {
+ n = 4;
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ L[3] = -L[3].z * L[2] + L[2].z * L[3];
+ }
+ else if (config == 7) /* V1 V2 V3 clip V4 */
+ {
+ n = 5;
+ L[4] = -L[3].z * L[0] + L[0].z * L[3];
+ L[3] = -L[3].z * L[2] + L[2].z * L[3];
+ }
+ else if (config == 8) /* V4 clip V1 V2 V3 */
+ {
+ n = 3;
+ L[0] = -L[0].z * L[3] + L[3].z * L[0];
+ L[1] = -L[2].z * L[3] + L[3].z * L[2];
+ L[2] = L[3];
+ }
+ else if (config == 9) /* V1 V4 clip V2 V3 */
+ {
+ n = 4;
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ L[2] = -L[2].z * L[3] + L[3].z * L[2];
+ }
+ else if (config == 10) /* V2 V4 clip V1 V3) impossible */
+ {
+ n = 0;
+ }
+ else if (config == 11) /* V1 V2 V4 clip V3 */
+ {
+ n = 5;
+ L[4] = L[3];
+ L[3] = -L[2].z * L[3] + L[3].z * L[2];
+ L[2] = -L[2].z * L[1] + L[1].z * L[2];
+ }
+ else if (config == 12) /* V3 V4 clip V1 V2 */
+ {
+ n = 4;
+ L[1] = -L[1].z * L[2] + L[2].z * L[1];
+ L[0] = -L[0].z * L[3] + L[3].z * L[0];
+ }
+ else if (config == 13) /* V1 V3 V4 clip V2 */
+ {
+ n = 5;
+ L[4] = L[3];
+ L[3] = L[2];
+ L[2] = -L[1].z * L[2] + L[2].z * L[1];
+ L[1] = -L[1].z * L[0] + L[0].z * L[1];
+ }
+ else if (config == 14) /* V2 V3 V4 clip V1 */
+ {
+ n = 5;
+ L[4] = -L[0].z * L[3] + L[3].z * L[0];
+ L[0] = -L[0].z * L[1] + L[1].z * L[0];
+ }
+ else if (config == 15) /* V1 V2 V3 V4 */
+ {
+ n = 4;
+ }
+
+ if (n == 3)
+ L[3] = L[0];
+ if (n == 4)
+ L[4] = L[0];
+
+ return n;
+}
+
+vec2 ltc_coords(float cosTheta, float roughness)
+{
+ float theta = acos(cosTheta);
+ vec2 coords = vec2(roughness, theta/(0.5*3.14159));
+
+ /* scale and bias coordinates, for correct filtered lookup */
+ return coords * (LTC_LUT_SIZE - 1.0) / LTC_LUT_SIZE + 0.5 / LTC_LUT_SIZE;
+}
+
+mat3 ltc_matrix(vec2 coord)
+{
+ /* load inverse matrix */
+ vec4 t = texture(ltcMat, coord);
+ mat3 Minv = mat3(
+ vec3( 1, 0, t.y),
+ vec3( 0, t.z, 0),
+ vec3(t.w, 0, t.x)
+ );
+
+ return Minv;
+}
+
+float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4])
+{
+ /* construct orthonormal basis around N */
+ vec3 T1, T2;
+ T1 = normalize(V - N*dot(V, N));
+ T2 = cross(N, T1);
+
+ /* rotate area light in (T1, T2, R) basis */
+ Minv = Minv * transpose(mat3(T1, T2, N));
+
+ /* polygon (allocate 5 vertices for clipping) */
+ vec3 L[5];
+ L[0] = Minv * corners[0];
+ L[1] = Minv * corners[1];
+ L[2] = Minv * corners[2];
+ L[3] = Minv * corners[3];
+
+ int n = clip_quad_to_horizon(L);
+
+ if (n == 0)
+ return 0.0;
+
+ /* project onto sphere */
+ L[0] = normalize(L[0]);
+ L[1] = normalize(L[1]);
+ L[2] = normalize(L[2]);
+ L[3] = normalize(L[3]);
+ L[4] = normalize(L[4]);
+
+ /* integrate */
+ float sum = 0.0;
+
+ sum += edge_integral(L[0], L[1]);
+ sum += edge_integral(L[1], L[2]);
+ sum += edge_integral(L[2], L[3]);
+ if (n >= 4)
+ sum += edge_integral(L[3], L[4]);
+ if (n == 5)
+ sum += edge_integral(L[4], L[0]);
+
+ return abs(sum);
+}
+
+/* Aproximate circle with an octogone */
+#define LTC_CIRCLE_RES 8
+float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES])
+{
+ /* construct orthonormal basis around N */
+ vec3 T1, T2;
+ T1 = normalize(V - N*dot(V, N));
+ T2 = cross(N, T1);
+
+ /* rotate area light in (T1, T2, R) basis */
+ Minv = Minv * transpose(mat3(T1, T2, N));
+
+ for (int i = 0; i < LTC_CIRCLE_RES; ++i) {
+ p[i] = Minv * p[i];
+ /* clip to horizon */
+ p[i].z = max(0.0, p[i].z);
+ /* project onto sphere */
+ p[i] = normalize(p[i]);
+ }
+
+ /* integrate */
+ float sum = 0.0;
+ for (int i = 0; i < LTC_CIRCLE_RES - 1; ++i) {
+ sum += edge_integral(p[i], p[i + 1]);
+ }
+ sum += edge_integral(p[LTC_CIRCLE_RES - 1], p[0]);
+
+ return max(0.0, sum);
+}
+
diff --git a/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl b/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl
new file mode 100644
index 00000000000..cb2ceb5ed07
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl
@@ -0,0 +1,28 @@
+
+uniform sampler2D hdrColorBuf;
+
+in vec4 uvcoordsvar;
+
+out vec4 fragColor;
+
+float linearrgb_to_srgb(float c)
+{
+ if (c < 0.0031308)
+ return (c < 0.0) ? 0.0 : c * 12.92;
+ else
+ return 1.055 * pow(c, 1.0 / 2.4) - 0.055;
+}
+
+void linearrgb_to_srgb(vec4 col_from, out vec4 col_to)
+{
+ col_to.r = linearrgb_to_srgb(col_from.r);
+ col_to.g = linearrgb_to_srgb(col_from.g);
+ col_to.b = linearrgb_to_srgb(col_from.b);
+ col_to.a = col_from.a;
+}
+
+void main() {
+ fragColor = texture(hdrColorBuf, uvcoordsvar.st);
+
+ linearrgb_to_srgb(fragColor, fragColor);
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 78edae803b5..8a6f0b4511a 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -44,27 +44,57 @@
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
-#include "draw_mode_pass.h"
+#include "draw_common.h"
#include "draw_cache.h"
+#include "draw_view.h"
#include "MEM_guardedalloc.h"
#include "RE_engine.h"
-//#define WITH_VIEWPORT_CACHE_TEST
-
+struct bContext;
struct GPUFrameBuffer;
struct GPUShader;
struct GPUTexture;
struct GPUUniformBuffer;
struct Object;
struct Batch;
+struct DefaultFramebufferList;
+struct DefaultTextureList;
typedef struct DRWUniform DRWUniform;
typedef struct DRWInterface DRWInterface;
typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
+typedef struct DrawEngineType {
+ struct DrawEngineType *next, *prev;
+
+ char idname[32];
+
+ void (*engine_init)(void *vedata);
+ void (*engine_free)(void);
+
+ void (*cache_init)(void *vedata);
+ void (*cache_populate)(void *vedata, struct Object *ob);
+ void (*cache_finish)(void *vedata);
+
+ void (*draw_background)(void *vedata);
+ void (*draw_scene)(void *vedata);
+} DrawEngineType;
+
+#ifndef __DRW_ENGINE_H__
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+ struct GPUFrameBuffer *default_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+ struct GPUTexture *color;
+ struct GPUTexture *depth;
+} DefaultTextureList;
+#endif
+
/* Textures */
typedef enum {
@@ -92,11 +122,11 @@ typedef enum {
} DRWTextureFlag;
struct GPUTexture *DRW_texture_create_1D(
- int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+ int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D(
- int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+ int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_2D_array(
- int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels);
+ int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels);
void DRW_texture_free(struct GPUTexture *tex);
/* UBOs */
@@ -131,31 +161,41 @@ typedef struct DRWFboTexture {
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
+void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth);
/* Shaders */
struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_with_lib(const char *vert, const char *geom, const char *frag, const char *lib, const char *defines);
struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_3D_depth_only(void);
void DRW_shader_free(struct GPUShader *shader);
/* Batches */
typedef enum {
- DRW_STATE_WRITE_DEPTH = (1 << 0),
- DRW_STATE_WRITE_COLOR = (1 << 1),
- DRW_STATE_DEPTH_LESS = (1 << 2),
- DRW_STATE_DEPTH_EQUAL = (1 << 3),
- DRW_STATE_CULL_BACK = (1 << 4),
- DRW_STATE_CULL_FRONT = (1 << 5),
- DRW_STATE_WIRE = (1 << 6),
- DRW_STATE_WIRE_LARGE = (1 << 7),
- DRW_STATE_POINT = (1 << 8),
- DRW_STATE_STIPPLE_2 = (1 << 9),
- DRW_STATE_STIPPLE_3 = (1 << 10),
- DRW_STATE_STIPPLE_4 = (1 << 11),
- DRW_STATE_BLEND = (1 << 12),
+ DRW_STATE_WRITE_DEPTH = (1 << 0),
+ DRW_STATE_WRITE_COLOR = (1 << 1),
+ DRW_STATE_DEPTH_LESS = (1 << 2),
+ DRW_STATE_DEPTH_EQUAL = (1 << 3),
+ DRW_STATE_DEPTH_GREATER = (1 << 4),
+ DRW_STATE_CULL_BACK = (1 << 5),
+ DRW_STATE_CULL_FRONT = (1 << 6),
+ DRW_STATE_WIRE = (1 << 7),
+ DRW_STATE_WIRE_LARGE = (1 << 8),
+ DRW_STATE_POINT = (1 << 9),
+ DRW_STATE_STIPPLE_2 = (1 << 10),
+ DRW_STATE_STIPPLE_3 = (1 << 11),
+ DRW_STATE_STIPPLE_4 = (1 << 12),
+ DRW_STATE_BLEND = (1 << 13),
+
+ DRW_STATE_WRITE_STENCIL_SELECT = (1 << 14),
+ DRW_STATE_WRITE_STENCIL_ACTIVE = (1 << 15),
+ DRW_STATE_TEST_STENCIL_SELECT = (1 << 16),
+ DRW_STATE_TEST_STENCIL_ACTIVE = (1 << 17),
} DRWState;
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
@@ -172,7 +212,7 @@ void DRW_shgroup_attrib_float(DRWShadingGroup *shgroup, const char *name, int si
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, int loc);
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo, int loc);
-void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc);
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, struct GPUTexture **tex, int loc);
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
@@ -190,11 +230,12 @@ DRWPass *DRW_pass_create(const char *name, DRWState state);
/* Viewport */
typedef enum {
DRW_MAT_PERS,
- DRW_MAT_WIEW,
+ DRW_MAT_VIEW,
+ DRW_MAT_VIEWINV,
DRW_MAT_WIN,
} DRWViewportMatrixType;
-void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage);
+void DRW_viewport_init(const bContext *C);
void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
float *DRW_viewport_size_get(void);
float *DRW_viewport_screenvecs_get(void);
@@ -202,20 +243,24 @@ float *DRW_viewport_pixelsize_get(void);
bool DRW_viewport_is_persp_get(void);
bool DRW_viewport_cache_is_dirty(void);
+struct DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void);
+struct DefaultTextureList *DRW_viewport_texture_list_get(void);
+
+/* Objects */
+void **DRW_object_engine_data_get(Object *ob, DrawEngineType *det);
+
/* Settings */
-#ifndef __DRW_ENGINE_H__
-void *DRW_material_settings_get(Material *ma, const char *engine_name);
-void *DRW_render_settings_get(Scene *scene, const char *engine_name);
-#endif /* __DRW_ENGINE_H__ */
+bool DRW_is_object_renderable(struct Object *ob);
/* Draw commands */
-void DRW_draw_background(void);
-void DRW_centercircle(const float co[3]);
void DRW_draw_pass(DRWPass *pass);
+void DRW_draw_callbacks_pre_scene(void);
+void DRW_draw_callbacks_post_scene(void);
+
void DRW_state_reset(void);
/* Other */
void DRW_get_dfdy_factors(float dfdyfac[2]);
-
-#endif /* __DRW_RENDER_H__ */ \ No newline at end of file
+const struct bContext *DRW_get_context(void);
+#endif /* __DRW_RENDER_H__ */
diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c
new file mode 100644
index 00000000000..4a700388a7c
--- /dev/null
+++ b/source/blender/draw/intern/draw_armature.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_armature.c
+ * \ingroup draw
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_object_types.h"
+
+#include "DRW_render.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_dlrbTree.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_animsys.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
+#include "BKE_global.h"
+#include "BKE_modifier.h"
+#include "BKE_nla.h"
+#include "BKE_curve.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "ED_armature.h"
+#include "ED_keyframes_draw.h"
+
+#include "UI_resources.h"
+
+#include "draw_common.h"
+
+#define BONE_VAR(eBone, pchan, var) ((eBone) ? (eBone->var) : (pchan->var))
+#define BONE_FLAG(eBone, pchan) ((eBone) ? (eBone->flag) : (pchan->bone->flag))
+
+static Object *current_armature;
+/* Reset when changing current_armature */
+static DRWShadingGroup *bone_octahedral_solid;
+static DRWShadingGroup *bone_octahedral_wire;
+static DRWShadingGroup *bone_point_solid;
+static DRWShadingGroup *bone_point_wire;
+static DRWShadingGroup *bone_axes;
+static DRWShadingGroup *relationship_lines;
+
+static DRWPass *bone_solid;
+static DRWPass *bone_wire;
+
+/* Octahedral */
+static void DRW_shgroup_bone_octahedral_solid(const float (*bone_mat)[4], const float color[4])
+{
+ if (bone_octahedral_solid == NULL) {
+ struct Batch *geom = DRW_cache_bone_octahedral_get();
+ bone_octahedral_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat);
+ }
+
+ DRW_shgroup_dynamic_call_add(bone_octahedral_solid, bone_mat, color);
+}
+
+static void DRW_shgroup_bone_octahedral_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (bone_octahedral_wire == NULL) {
+ struct Batch *geom = DRW_cache_bone_octahedral_wire_outline_get();
+ bone_octahedral_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat);
+ }
+
+ DRW_shgroup_dynamic_call_add(bone_octahedral_wire, bone_mat, color);
+}
+
+/* Head and tail sphere */
+static void DRW_shgroup_bone_point_solid(const float (*bone_mat)[4], const float color[4])
+{
+ if (bone_point_solid == NULL) {
+ struct Batch *geom = DRW_cache_bone_point_get();
+ bone_point_solid = shgroup_instance_objspace_solid(bone_solid, geom, current_armature->obmat);
+ }
+
+ DRW_shgroup_dynamic_call_add(bone_point_solid, bone_mat, color);
+}
+
+static void DRW_shgroup_bone_point_wire(const float (*bone_mat)[4], const float color[4])
+{
+ if (bone_point_wire == NULL) {
+ struct Batch *geom = DRW_cache_bone_point_wire_outline_get();
+ bone_point_wire = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat);
+ }
+
+ DRW_shgroup_dynamic_call_add(bone_point_wire, bone_mat, color);
+}
+
+/* Axes */
+static void DRW_shgroup_bone_axes(const float (*bone_mat)[4], const float color[4])
+{
+ if (bone_axes == NULL) {
+ struct Batch *geom = DRW_cache_bone_arrows_get();
+ bone_axes = shgroup_instance_objspace_wire(bone_wire, geom, current_armature->obmat);
+ }
+
+ DRW_shgroup_dynamic_call_add(bone_axes, bone_mat, color);
+}
+
+/* Relationship lines */
+static void UNUSED_FUNCTION(DRW_shgroup_bone_relationship_lines)(const float head[3], const float tail[3])
+{
+ DRW_shgroup_dynamic_call_add(relationship_lines, head);
+ DRW_shgroup_dynamic_call_add(relationship_lines, tail);
+}
+
+/* *************** Armature Drawing - Coloring API ***************************** */
+
+static float colorBoneSolid[4];
+static float colorTextHi[4];
+static float colorText[4];
+static float colorVertexSelect[4];
+static float colorVertex[4];
+
+static const float *constColor;
+
+static void update_color(const float const_color[4])
+{
+ constColor = const_color;
+
+ UI_GetThemeColor4fv(TH_BONE_SOLID, colorBoneSolid);
+ UI_GetThemeColor4fv(TH_TEXT_HI, colorTextHi);
+ UI_GetThemeColor4fv(TH_TEXT, colorText);
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, colorVertexSelect);
+ UI_GetThemeColor4fv(TH_VERTEX, colorVertex);
+}
+
+static const float *get_bone_solid_color(EditBone *eBone, bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ if (constColor)
+ return colorBoneSolid;
+
+ /* Edit Mode */
+ if (eBone) {
+ if (eBone->flag & BONE_SELECTED)
+ return colorVertexSelect;
+ }
+
+ return colorBoneSolid;
+}
+
+static const float *get_bone_wire_color(EditBone *eBone, bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ if (constColor)
+ return constColor;
+
+ if (eBone) {
+ if (eBone->flag & BONE_SELECTED)
+ return colorVertexSelect;
+ }
+
+ return colorVertex;
+}
+
+/* *************** Armature drawing, helper calls for parts ******************* */
+
+static void draw_bone_update_disp_matrix(EditBone *eBone, bPoseChannel *pchan, int drawtype)
+{
+ float s[4][4], ebmat[4][4];
+ float length;
+ float (*bone_mat)[4];
+ float (*disp_mat)[4];
+ float (*disp_tail_mat)[4];
+
+ /* TODO : This should be moved to depsgraph or armature refresh
+ * and not be tight to the draw pass creation.
+ * This would refresh armature without invalidating the draw cache */
+ if (pchan) {
+ length = pchan->bone->length;
+ bone_mat = pchan->pose_mat;
+ disp_mat = pchan->disp_mat;
+ disp_tail_mat = pchan->disp_tail_mat;
+ }
+ else {
+ eBone->length = len_v3v3(eBone->tail, eBone->head);
+ ED_armature_ebone_to_mat4(eBone, ebmat);
+
+ length = eBone->length;
+ bone_mat = ebmat;
+ disp_mat = eBone->disp_mat;
+ disp_tail_mat = eBone->disp_tail_mat;
+ }
+
+ if (pchan && pchan->custom) {
+ /* TODO */
+ }
+ else if (drawtype == ARM_ENVELOPE) {
+ /* TODO */
+ }
+ else if (drawtype == ARM_LINE) {
+ /* TODO */
+ }
+ else if (drawtype == ARM_WIRE) {
+ /* TODO */
+ }
+ else if (drawtype == ARM_B_BONE) {
+ /* TODO */
+ }
+ else {
+ scale_m4_fl(s, length);
+ mul_m4_m4m4(disp_mat, bone_mat, s);
+ copy_m4_m4(disp_tail_mat, disp_mat);
+ translate_m4(disp_tail_mat, 0.0f, 1.0f, 0.0f);
+ }
+}
+
+static void draw_axes(EditBone *eBone, bPoseChannel *pchan)
+{
+ const float *col = (constColor) ? constColor :
+ (BONE_FLAG(eBone, pchan) & BONE_SELECTED) ? colorTextHi : colorText;
+
+ DRW_shgroup_bone_axes(BONE_VAR(eBone, pchan, disp_tail_mat), col);
+}
+
+static void draw_points(EditBone *eBone, bPoseChannel *pchan, bArmature *arm)
+{
+ const float *col_solid_root = colorBoneSolid;
+ const float *col_solid_tail = colorBoneSolid;
+ const float *col_wire_root = (constColor) ? constColor : colorVertex;
+ const float *col_wire_tail = (constColor) ? constColor : colorVertex;
+
+ /* Edit bone points can be selected */
+ if (eBone) {
+ if (eBone->flag & BONE_ROOTSEL) {
+ col_solid_root = colorVertexSelect;
+ col_wire_root = colorVertexSelect;
+ }
+ if (eBone->flag & BONE_TIPSEL) {
+ col_solid_tail = colorVertexSelect;
+ col_wire_tail = colorVertexSelect;
+ }
+ }
+
+ /* Draw root point if we are not connected and parent are not hidden */
+ if ((BONE_FLAG(eBone, pchan) & BONE_CONNECTED) == 0) {
+ if (eBone) {
+ if (!((eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))) {
+ DRW_shgroup_bone_point_solid(eBone->disp_mat, col_solid_root);
+ DRW_shgroup_bone_point_wire(eBone->disp_mat, col_wire_root);
+ }
+ }
+ else {
+ Bone *bone = pchan->bone;
+ if (!((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)))) {
+ DRW_shgroup_bone_point_solid(pchan->disp_mat, col_solid_root);
+ DRW_shgroup_bone_point_wire(pchan->disp_mat, col_wire_root);
+ }
+ }
+ }
+
+ /* Draw tip point */
+ DRW_shgroup_bone_point_solid(BONE_VAR(eBone, pchan, disp_tail_mat), col_solid_tail);
+ DRW_shgroup_bone_point_wire(BONE_VAR(eBone, pchan, disp_tail_mat), col_wire_tail);
+}
+
+static void draw_bone_custom_shape(EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_envelope(EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_line(EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_wire(EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_box(EditBone *UNUSED(eBone), bPoseChannel *UNUSED(pchan), bArmature *UNUSED(arm))
+{
+ /* work in progress -- fclem */
+}
+
+static void draw_bone_octahedral(EditBone *eBone, bPoseChannel *pchan, bArmature *arm)
+{
+ const float *col_solid = get_bone_solid_color(eBone, pchan, arm);
+ const float *col_wire = get_bone_wire_color(eBone, pchan, arm);
+
+ DRW_shgroup_bone_octahedral_solid(BONE_VAR(eBone, pchan, disp_mat), col_solid);
+ DRW_shgroup_bone_octahedral_wire(BONE_VAR(eBone, pchan, disp_mat), col_wire);
+
+ draw_points(eBone, pchan, arm);
+}
+
+static void draw_armature_edit(Object *ob)
+{
+ EditBone *eBone;
+ bArmature *arm = ob->data;
+ unsigned int index;
+
+ update_color(NULL);
+
+ for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
+ if (eBone->layer & arm->layer) {
+ if ((eBone->flag & BONE_HIDDEN_A) == 0) {
+
+ draw_bone_update_disp_matrix(eBone, NULL, arm->drawtype);
+
+ if (arm->drawtype == ARM_ENVELOPE)
+ draw_bone_envelope(eBone, NULL, arm);
+ else if (arm->drawtype == ARM_LINE)
+ draw_bone_line(eBone, NULL, arm);
+ else if (arm->drawtype == ARM_WIRE)
+ draw_bone_wire(eBone, NULL, arm);
+ else if (arm->drawtype == ARM_B_BONE)
+ draw_bone_box(eBone, NULL, arm);
+ else
+ draw_bone_octahedral(eBone, NULL, arm);
+
+ /* Draw additional axes */
+ if (arm->flag & ARM_DRAWAXES)
+ draw_axes(eBone, NULL);
+ }
+ }
+ }
+}
+
+/* if const_color is NULL do pose mode coloring */
+static void draw_armature_pose(Object *ob, const float const_color[4])
+{
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan;
+ Bone *bone;
+
+ update_color(const_color);
+
+ /* We can't safely draw non-updated pose, might contain NULL bone pointers... */
+ if (ob->pose->flag & POSE_RECALC) {
+ BKE_pose_rebuild(ob, arm);
+ }
+
+ /* being set below */
+ arm->layer_used = 0;
+
+ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
+ bone = pchan->bone;
+ arm->layer_used |= bone->layer;
+
+ /* bone must be visible */
+ if ((bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG)) == 0) {
+ if (bone->layer & arm->layer) {
+
+ draw_bone_update_disp_matrix(NULL, pchan, arm->drawtype);
+
+ if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM))
+ draw_bone_custom_shape(NULL, pchan, arm);
+ else if (arm->drawtype == ARM_ENVELOPE)
+ draw_bone_envelope(NULL, pchan, arm);
+ else if (arm->drawtype == ARM_LINE)
+ draw_bone_line(NULL, pchan, arm);
+ else if (arm->drawtype == ARM_WIRE)
+ draw_bone_wire(NULL, pchan, arm);
+ else if (arm->drawtype == ARM_B_BONE)
+ draw_bone_box(NULL, pchan, arm);
+ else
+ draw_bone_octahedral(NULL, pchan, arm);
+
+ /* Draw additional axes */
+ if (arm->flag & ARM_DRAWAXES)
+ draw_axes(NULL, pchan);
+ }
+ }
+ }
+}
+
+/* this function set the object space to use
+ * for all subsequent DRW_shgroup_bone_*** calls */
+static void DRW_shgroup_armature(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines)
+{
+ current_armature = ob;
+ bone_octahedral_solid = NULL;
+ bone_octahedral_wire = NULL;
+ bone_point_solid = NULL;
+ bone_point_wire = NULL;
+ bone_axes = NULL;
+
+ bone_solid = pass_bone_solid;
+ bone_wire = pass_bone_wire;
+ relationship_lines = shgrp_relationship_lines;
+}
+
+void DRW_shgroup_armature_object(
+ Object *ob, SceneLayer *sl, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines)
+{
+ float *color;
+ DRW_object_wire_theme_get(ob, sl, &color);
+
+ DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines);
+ draw_armature_pose(ob, color);
+}
+
+void DRW_shgroup_armature_pose(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines)
+{
+ DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines);
+ draw_armature_pose(ob, NULL);
+}
+
+void DRW_shgroup_armature_edit(
+ Object *ob, DRWPass *pass_bone_solid, DRWPass *pass_bone_wire, DRWShadingGroup *shgrp_relationship_lines)
+{
+ DRW_shgroup_armature(ob, pass_bone_solid, pass_bone_wire, shgrp_relationship_lines);
+ draw_armature_edit(ob);
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 7ea6b8d0066..0d79011d267 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -37,19 +37,35 @@
#include "draw_cache.h"
-static struct DRWShapeCache{
+static struct DRWShapeCache {
Batch *drw_single_vertice;
Batch *drw_fullscreen_quad;
Batch *drw_plain_axes;
Batch *drw_single_arrow;
Batch *drw_cube;
Batch *drw_circle;
+ Batch *drw_square;
Batch *drw_line;
+ Batch *drw_line_endpoints;
Batch *drw_empty_sphere;
Batch *drw_empty_cone;
Batch *drw_arrows;
+ Batch *drw_axis_names;
Batch *drw_lamp;
Batch *drw_lamp_sunrays;
+ Batch *drw_lamp_area;
+ Batch *drw_lamp_hemi;
+ Batch *drw_lamp_spot;
+ Batch *drw_lamp_spot_square;
+ Batch *drw_speaker;
+ Batch *drw_bone_octahedral;
+ Batch *drw_bone_octahedral_wire;
+ Batch *drw_bone_point;
+ Batch *drw_bone_point_wire;
+ Batch *drw_bone_arrows;
+ Batch *drw_camera;
+ Batch *drw_camera_tria;
+ Batch *drw_camera_focus;
} SHC = {NULL};
void DRW_shape_cache_free(void)
@@ -66,48 +82,195 @@ void DRW_shape_cache_free(void)
Batch_discard_all(SHC.drw_cube);
if (SHC.drw_circle)
Batch_discard_all(SHC.drw_circle);
+ if (SHC.drw_square)
+ Batch_discard_all(SHC.drw_square);
if (SHC.drw_line)
Batch_discard_all(SHC.drw_line);
+ if (SHC.drw_line_endpoints)
+ Batch_discard_all(SHC.drw_line_endpoints);
if (SHC.drw_empty_sphere)
Batch_discard_all(SHC.drw_empty_sphere);
if (SHC.drw_empty_cone)
Batch_discard_all(SHC.drw_empty_cone);
if (SHC.drw_arrows)
Batch_discard_all(SHC.drw_arrows);
+ if (SHC.drw_axis_names)
+ Batch_discard_all(SHC.drw_axis_names);
if (SHC.drw_lamp)
Batch_discard_all(SHC.drw_lamp);
if (SHC.drw_lamp_sunrays)
Batch_discard_all(SHC.drw_lamp_sunrays);
+ if (SHC.drw_lamp_area)
+ Batch_discard_all(SHC.drw_lamp_area);
+ if (SHC.drw_lamp_hemi)
+ Batch_discard_all(SHC.drw_lamp_hemi);
+ if (SHC.drw_lamp_spot)
+ Batch_discard_all(SHC.drw_lamp_spot);
+ if (SHC.drw_lamp_spot_square)
+ Batch_discard_all(SHC.drw_lamp_spot_square);
+ if (SHC.drw_speaker)
+ Batch_discard_all(SHC.drw_speaker);
+ if (SHC.drw_bone_octahedral)
+ Batch_discard_all(SHC.drw_bone_octahedral);
+ if (SHC.drw_bone_octahedral_wire)
+ Batch_discard_all(SHC.drw_bone_octahedral_wire);
+ if (SHC.drw_bone_point)
+ Batch_discard_all(SHC.drw_bone_point);
+ if (SHC.drw_bone_point_wire)
+ Batch_discard_all(SHC.drw_bone_point_wire);
+ if (SHC.drw_bone_arrows)
+ Batch_discard_all(SHC.drw_bone_arrows);
+ if (SHC.drw_camera)
+ Batch_discard_all(SHC.drw_camera);
+ if (SHC.drw_camera_tria)
+ Batch_discard_all(SHC.drw_camera_tria);
+ if (SHC.drw_camera_focus)
+ Batch_discard_all(SHC.drw_camera_focus);
+}
+
+/* Helper functions */
+
+static void add_fancy_edge(VertexBuffer *vbo, unsigned int pos_id, unsigned int n1_id, unsigned int n2_id,
+ unsigned int *v_idx, const float co1[3], const float co2[3],
+ const float n1[3], const float n2[3])
+{
+ setAttrib(vbo, n1_id, *v_idx, n1);
+ setAttrib(vbo, n2_id, *v_idx, n2);
+ setAttrib(vbo, pos_id, (*v_idx)++, co1);
+
+ setAttrib(vbo, n1_id, *v_idx, n1);
+ setAttrib(vbo, n2_id, *v_idx, n2);
+ setAttrib(vbo, pos_id, (*v_idx)++, co2);
+}
+
+static void add_lat_lon_vert(VertexBuffer *vbo, unsigned int pos_id, unsigned int nor_id,
+ unsigned int *v_idx, const float rad, const float lat, const float lon)
+{
+ float pos[3], nor[3];
+ nor[0] = sinf(lat) * cosf(lon);
+ nor[1] = cosf(lat);
+ nor[2] = sinf(lat) * sinf(lon);
+ mul_v3_v3fl(pos, nor, rad);
+
+ setAttrib(vbo, nor_id, *v_idx, nor);
+ setAttrib(vbo, pos_id, (*v_idx)++, pos);
+}
+
+static VertexBuffer *fill_arrows_vbo(const float scale)
+{
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ /* Line */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 6 * 3);
+
+ float v1[3] = {0.0, 0.0, 0.0};
+ float v2[3] = {0.0, 0.0, 0.0};
+ float vtmp1[3], vtmp2[3];
+
+ for (int axis = 0; axis < 3; axis++) {
+ const int arrow_axis = (axis == 0) ? 1 : 0;
+
+ v2[axis] = 1.0f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ setAttrib(vbo, pos_id, axis * 6 + 0, vtmp1);
+ setAttrib(vbo, pos_id, axis * 6 + 1, vtmp2);
+
+ v1[axis] = 0.85f;
+ v1[arrow_axis] = -0.08f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ setAttrib(vbo, pos_id, axis * 6 + 2, vtmp1);
+ setAttrib(vbo, pos_id, axis * 6 + 3, vtmp2);
+
+ v1[arrow_axis] = 0.08f;
+ mul_v3_v3fl(vtmp1, v1, scale);
+ mul_v3_v3fl(vtmp2, v2, scale);
+ setAttrib(vbo, pos_id, axis * 6 + 4, vtmp1);
+ setAttrib(vbo, pos_id, axis * 6 + 5, vtmp2);
+
+ /* reset v1 & v2 to zero */
+ v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
+ }
+
+ return vbo;
+}
+
+static VertexBuffer *sphere_wire_vbo(const float rad)
+{
+#define NSEGMENTS 16
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
+
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = rad * cosf(angle);
+ p[i][1] = rad * sinf(angle);
+ }
+
+ for (int axis = 0; axis < 3; ++axis) {
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ float cv[2], v[3];
+
+ cv[0] = p[(i + j) % NSEGMENTS][0];
+ cv[1] = p[(i + j) % NSEGMENTS][1];
+
+ if (axis == 0)
+ v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
+ else if (axis == 1)
+ v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+ else
+ v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1];
+
+ setAttrib(vbo, pos_id, i * 2 + j + (NSEGMENTS * 2 * axis), v);
+ }
+ }
+ }
+
+ return vbo;
+#undef NSEGMENTS
}
/* Quads */
Batch *DRW_cache_fullscreen_quad_get(void)
{
if (!SHC.drw_fullscreen_quad) {
- float v1[2] = {-1.0f, -1.0f};
- float v2[2] = { 1.0f, -1.0f};
- float v3[2] = {-1.0f, 1.0f};
- float v4[2] = { 1.0f, 1.0f};
+ float pos[4][2] = {{-1.0f, -1.0f}, { 1.0f, -1.0f}, {-1.0f, 1.0f}, { 1.0f, 1.0f}};
+ float uvs[4][2] = {{ 0.0f, 0.0f}, { 1.0f, 0.0f}, { 0.0f, 1.0f}, { 1.0f, 1.0f}};
- /* Position Only 3D format */
+ /* Position Only 2D format */
static VertexFormat format = { 0 };
- static unsigned pos_id;
+ static unsigned pos_id, uvs_id;
if (format.attrib_ct == 0) {
- pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ uvs_id = add_attrib(&format, "uvs", GL_FLOAT, 2, KEEP_FLOAT);
}
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
- VertexBuffer_allocate_data(vbo, 6);
+ VertexBuffer_allocate_data(vbo, 4);
- setAttrib(vbo, pos_id, 0, v1);
- setAttrib(vbo, pos_id, 1, v2);
- setAttrib(vbo, pos_id, 2, v3);
-
- setAttrib(vbo, pos_id, 3, v2);
- setAttrib(vbo, pos_id, 4, v3);
- setAttrib(vbo, pos_id, 5, v4);
+ for (int i = 0; i < 4; ++i) {
+ setAttrib(vbo, pos_id, i, pos[i]);
+ setAttrib(vbo, uvs_id, i, uvs[i]);
+ }
- SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLES, vbo, NULL);
+ SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLE_STRIP, vbo, NULL);
}
return SHC.drw_fullscreen_quad;
}
@@ -128,7 +291,7 @@ Batch *DRW_cache_cube_get(void)
{ 1.0f, 1.0f, 1.0f}
};
- const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+ const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6};
/* Position Only 3D format */
static VertexFormat format = { 0 };
@@ -167,13 +330,13 @@ Batch *DRW_cache_circle_get(void)
for (int a = 0; a < CIRCLE_RESOL; a++) {
v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
- v[2] = 0.0f;
+ v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[1] = 0.0f;
setAttrib(vbo, pos_id, a * 2, v);
v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
- v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
- v[2] = 0.0f;
+ v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[1] = 0.0f;
setAttrib(vbo, pos_id, a * 2 + 1, v);
}
@@ -183,6 +346,34 @@ Batch *DRW_cache_circle_get(void)
#undef CIRCLE_RESOL
}
+Batch *DRW_cache_square_get(void)
+{
+ if (!SHC.drw_square) {
+ float p[4][3] = {{ 1.0f, 0.0f, 1.0f},
+ { 1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, -1.0f},
+ {-1.0f, 0.0f, 1.0f}};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 8);
+
+ for (int i = 0; i < 4; i++) {
+ setAttrib(vbo, pos_id, i * 2, p[i % 4]);
+ setAttrib(vbo, pos_id, i * 2 + 1, p[(i+1) % 4]);
+ }
+
+ SHC.drw_square = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_square;
+}
+
Batch *DRW_cache_single_line_get(void)
{
/* Z axis line */
@@ -208,6 +399,32 @@ Batch *DRW_cache_single_line_get(void)
return SHC.drw_line;
}
+
+Batch *DRW_cache_single_line_endpoints_get(void)
+{
+ /* Z axis line */
+ if (!SHC.drw_line_endpoints) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+ float v2[3] = {0.0f, 0.0f, 1.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 2);
+
+ setAttrib(vbo, pos_id, 0, v1);
+ setAttrib(vbo, pos_id, 1, v2);
+
+ SHC.drw_line_endpoints = Batch_create(GL_POINTS, vbo, NULL);
+ }
+ return SHC.drw_line_endpoints;
+}
+
/* Empties */
Batch *DRW_cache_plain_axes_get(void)
{
@@ -245,7 +462,7 @@ Batch *DRW_cache_plain_axes_get(void)
Batch *DRW_cache_single_arrow_get(void)
{
if (!SHC.drw_single_arrow) {
- float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3], v3[3];
+ float v1[3] = {0.0f, 0.0f, 1.0f}, v2[3], v3[3];
/* Position Only 3D format */
static VertexFormat format = { 0 };
@@ -284,50 +501,11 @@ Batch *DRW_cache_single_arrow_get(void)
Batch *DRW_cache_empty_sphere_get(void)
{
-#define NSEGMENTS 16
if (!SHC.drw_empty_sphere) {
- /* a single ring of vertices */
- float p[NSEGMENTS][2];
- for (int i = 0; i < NSEGMENTS; ++i) {
- float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
- p[i][0] = cosf(angle);
- p[i][1] = sinf(angle);
- }
-
- /* Position Only 3D format */
- static VertexFormat format = { 0 };
- static unsigned pos_id;
- if (format.attrib_ct == 0) {
- pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
- }
-
- VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
- VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
-
- for (int axis = 0; axis < 3; ++axis) {
- for (int i = 0; i < NSEGMENTS; ++i) {
- for (int j = 0; j < 2; ++j) {
- float cv[2], v[3];
-
- cv[0] = p[(i+j) % NSEGMENTS][0];
- cv[1] = p[(i+j) % NSEGMENTS][1];
-
- if (axis == 0)
- v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
- else if (axis == 1)
- v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- else
- v[0] = 0.0f, v[1] = cv[0], v[2] = cv[1];
-
- setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v);
- }
- }
- }
-
+ VertexBuffer *vbo = sphere_wire_vbo(1.0f);
SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL);
}
return SHC.drw_empty_sphere;
-#undef NSEGMENTS
}
Batch *DRW_cache_empty_cone_get(void)
@@ -359,17 +537,17 @@ Batch *DRW_cache_empty_cone_get(void)
/* cone sides */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- setAttrib(vbo, pos_id, i*4, v);
+ setAttrib(vbo, pos_id, i * 4, v);
v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
- setAttrib(vbo, pos_id, i*4 + 1, v);
+ setAttrib(vbo, pos_id, i * 4 + 1, v);
/* end ring */
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- setAttrib(vbo, pos_id, i*4 + 2, v);
- cv[0] = p[(i+1) % NSEGMENTS][0];
- cv[1] = p[(i+1) % NSEGMENTS][1];
+ setAttrib(vbo, pos_id, i * 4 + 2, v);
+ cv[0] = p[(i + 1) % NSEGMENTS][0];
+ cv[1] = p[(i + 1) % NSEGMENTS][1];
v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
- setAttrib(vbo, pos_id, i*4 + 3, v);
+ setAttrib(vbo, pos_id, i * 4 + 3, v);
}
SHC.drw_empty_cone = Batch_create(GL_LINES, vbo, NULL);
@@ -381,43 +559,72 @@ Batch *DRW_cache_empty_cone_get(void)
Batch *DRW_cache_arrows_get(void)
{
if (!SHC.drw_arrows) {
- float v1[3] = {0.0, 0.0, 0.0};
- float v2[3] = {0.0, 0.0, 0.0};
+ VertexBuffer *vbo = fill_arrows_vbo(1.0f);
+
+ SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_arrows;
+}
+
+Batch *DRW_cache_axis_names_get(void)
+{
+ if (!SHC.drw_axis_names) {
+ const float size = 0.1f;
+ float v1[3], v2[3];
/* Position Only 3D format */
static VertexFormat format = { 0 };
static unsigned pos_id;
if (format.attrib_ct == 0) {
+ /* Using 3rd component as axis indicator */
pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
}
/* Line */
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
- VertexBuffer_allocate_data(vbo, 6 * 3);
-
- for (int axis = 0; axis < 3; axis++) {
- const int arrow_axis = (axis == 0) ? 1 : 0;
-
- v2[axis] = 1.0f;
- setAttrib(vbo, pos_id, axis * 6 + 0, v1);
- setAttrib(vbo, pos_id, axis * 6 + 1, v2);
-
- v1[axis] = 0.85f;
- v1[arrow_axis] = -0.08f;
- setAttrib(vbo, pos_id, axis * 6 + 2, v1);
- setAttrib(vbo, pos_id, axis * 6 + 3, v2);
+ VertexBuffer_allocate_data(vbo, 14);
- v1[arrow_axis] = 0.08f;
- setAttrib(vbo, pos_id, axis * 6 + 4, v1);
- setAttrib(vbo, pos_id, axis * 6 + 5, v2);
+ /* X */
+ copy_v3_fl3(v1, -size, size, 0.0f);
+ copy_v3_fl3(v2, size, -size, 0.0f);
+ setAttrib(vbo, pos_id, 0, v1);
+ setAttrib(vbo, pos_id, 1, v2);
- /* reset v1 & v2 to zero */
- v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
- }
+ copy_v3_fl3(v1, size, size, 0.0f);
+ copy_v3_fl3(v2, -size, -size, 0.0f);
+ setAttrib(vbo, pos_id, 2, v1);
+ setAttrib(vbo, pos_id, 3, v2);
- SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL);
+ /* Y */
+ copy_v3_fl3(v1, -size + 0.25f * size, size, 1.0f);
+ copy_v3_fl3(v2, 0.0f, 0.0f, 1.0f);
+ setAttrib(vbo, pos_id, 4, v1);
+ setAttrib(vbo, pos_id, 5, v2);
+
+ copy_v3_fl3(v1, size - 0.25f * size, size, 1.0f);
+ copy_v3_fl3(v2, -size + 0.25f * size, -size, 1.0f);
+ setAttrib(vbo, pos_id, 6, v1);
+ setAttrib(vbo, pos_id, 7, v2);
+
+ /* Z */
+ copy_v3_fl3(v1, -size, size, 2.0f);
+ copy_v3_fl3(v2, size, size, 2.0f);
+ setAttrib(vbo, pos_id, 8, v1);
+ setAttrib(vbo, pos_id, 9, v2);
+
+ copy_v3_fl3(v1, size, size, 2.0f);
+ copy_v3_fl3(v2, -size, -size, 2.0f);
+ setAttrib(vbo, pos_id, 10, v1);
+ setAttrib(vbo, pos_id, 11, v2);
+
+ copy_v3_fl3(v1, -size, -size, 2.0f);
+ copy_v3_fl3(v2, size, -size, 2.0f);
+ setAttrib(vbo, pos_id, 12, v1);
+ setAttrib(vbo, pos_id, 13, v2);
+
+ SHC.drw_axis_names = Batch_create(GL_LINES, vbo, NULL);
}
- return SHC.drw_arrows;
+ return SHC.drw_axis_names;
}
/* Lamps */
@@ -484,6 +691,533 @@ Batch *DRW_cache_lamp_sunrays_get(void)
return SHC.drw_lamp_sunrays;
}
+Batch *DRW_cache_lamp_area_get(void)
+{
+ if (!SHC.drw_lamp_area) {
+ float v1[3] = {0.0f, 0.0f, 0.0f};
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 8);
+
+ v1[0] = v1[1] = 0.5f;
+ setAttrib(vbo, pos_id, 0, v1);
+ v1[0] = -0.5f;
+ setAttrib(vbo, pos_id, 1, v1);
+ setAttrib(vbo, pos_id, 2, v1);
+ v1[1] = -0.5f;
+ setAttrib(vbo, pos_id, 3, v1);
+ setAttrib(vbo, pos_id, 4, v1);
+ v1[0] = 0.5f;
+ setAttrib(vbo, pos_id, 5, v1);
+ setAttrib(vbo, pos_id, 6, v1);
+ v1[1] = 0.5f;
+ setAttrib(vbo, pos_id, 7, v1);
+
+ SHC.drw_lamp_area = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp_area;
+}
+
+Batch *DRW_cache_lamp_hemi_get(void)
+{
+#define CIRCLE_RESOL 32
+ if (!SHC.drw_lamp_hemi) {
+ float v[3];
+ int vidx = 0;
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2 * 2 - 6 * 2 * 2);
+
+ /* XZ plane */
+ for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
+ v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2);
+ v[2] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
+ v[1] = 0.0f;
+ setAttrib(vbo, pos_id, vidx++, v);
+
+ v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2);
+ v[2] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL) - M_PI / 2) - 1.0f;
+ v[1] = 0.0f;
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+
+ /* XY plane */
+ for (int a = 3; a < CIRCLE_RESOL / 2 - 3; a++) {
+ v[2] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL)) - 1.0f;
+ v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[0] = 0.0f;
+ setAttrib(vbo, pos_id, vidx++, v);
+
+ v[2] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL)) - 1.0f;
+ v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[0] = 0.0f;
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+
+ /* YZ plane full circle */
+ /* lease v[2] as it is */
+ const float rad = cosf((2.0f * M_PI * 3) / ((float)CIRCLE_RESOL));
+ for (int a = 0; a < CIRCLE_RESOL; a++) {
+ v[1] = rad * sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ v[0] = rad * cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+ setAttrib(vbo, pos_id, vidx++, v);
+
+ v[1] = rad * sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ v[0] = rad * cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+
+
+ SHC.drw_lamp_hemi = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp_hemi;
+#undef CIRCLE_RESOL
+}
+
+
+Batch *DRW_cache_lamp_spot_get(void)
+{
+#define NSEGMENTS 32
+ if (!SHC.drw_lamp_spot) {
+ /* a single ring of vertices */
+ float p[NSEGMENTS][2];
+ float n[NSEGMENTS][3];
+ float neg[NSEGMENTS][3];
+ float half_angle = 2 * M_PI / ((float)NSEGMENTS * 2);
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+ p[i][0] = cosf(angle);
+ p[i][1] = sinf(angle);
+
+ n[i][0] = cosf(angle - half_angle);
+ n[i][1] = sinf(angle - half_angle);
+ n[i][2] = cosf(M_PI / 16.0f); /* slope of the cone */
+ normalize_v3(n[i]); /* necessary ? */
+ negate_v3_v3(neg[i], n[i]);
+ }
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned int pos_id, n1_id, n2_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ n1_id = add_attrib(&format, "N1", GL_FLOAT, 3, KEEP_FLOAT);
+ n2_id = add_attrib(&format, "N2", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
+
+ for (int i = 0; i < NSEGMENTS; ++i) {
+ float cv[2], v[3];
+ cv[0] = p[i % NSEGMENTS][0];
+ cv[1] = p[i % NSEGMENTS][1];
+
+ /* cone sides */
+ v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
+ setAttrib(vbo, pos_id, i * 4, v);
+ v[0] = 0.0f, v[1] = 0.0f, v[2] = 0.0f;
+ setAttrib(vbo, pos_id, i * 4 + 1, v);
+
+ setAttrib(vbo, n1_id, i * 4, n[(i) % NSEGMENTS]);
+ setAttrib(vbo, n1_id, i * 4 + 1, n[(i) % NSEGMENTS]);
+ setAttrib(vbo, n2_id, i * 4, n[(i+1) % NSEGMENTS]);
+ setAttrib(vbo, n2_id, i * 4 + 1, n[(i+1) % NSEGMENTS]);
+
+ /* end ring */
+ v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
+ setAttrib(vbo, pos_id, i * 4 + 2, v);
+ cv[0] = p[(i + 1) % NSEGMENTS][0];
+ cv[1] = p[(i + 1) % NSEGMENTS][1];
+ v[0] = cv[0], v[1] = cv[1], v[2] = -1.0f;
+ setAttrib(vbo, pos_id, i * 4 + 3, v);
+
+ setAttrib(vbo, n1_id, i * 4 + 2, n[(i) % NSEGMENTS]);
+ setAttrib(vbo, n1_id, i * 4 + 3, n[(i) % NSEGMENTS]);
+ setAttrib(vbo, n2_id, i * 4 + 2, neg[(i) % NSEGMENTS]);
+ setAttrib(vbo, n2_id, i * 4 + 3, neg[(i) % NSEGMENTS]);
+ }
+
+ SHC.drw_lamp_spot = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp_spot;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_lamp_spot_square_get(void)
+{
+ if (!SHC.drw_lamp_spot_square) {
+ float p[5][3] = {{ 0.0f, 0.0f, 0.0f},
+ { 1.0f, 1.0f, -1.0f},
+ { 1.0f, -1.0f, -1.0f},
+ {-1.0f, -1.0f, -1.0f},
+ {-1.0f, 1.0f, -1.0f}};
+
+ unsigned int v_idx = 0;
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned int pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 16);
+
+ /* piramid sides */
+ for (int i = 1; i <= 4; ++i) {
+ setAttrib(vbo, pos_id, v_idx++, p[0]);
+ setAttrib(vbo, pos_id, v_idx++, p[i]);
+
+ setAttrib(vbo, pos_id, v_idx++, p[(i % 4)+1]);
+ setAttrib(vbo, pos_id, v_idx++, p[((i+1) % 4)+1]);
+ }
+
+ SHC.drw_lamp_spot_square = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_lamp_spot_square;
+}
+
+/* Speaker */
+Batch *DRW_cache_speaker_get(void)
+{
+ if (!SHC.drw_speaker) {
+ float v[3];
+ const int segments = 16;
+ int vidx = 0;
+
+ /* Position Only 3D format */
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 3 * segments * 2 + 4 * 4);
+
+ for (int j = 0; j < 3; j++) {
+ float z = 0.25f * j - 0.125f;
+ float r = (j == 0 ? 0.5f : 0.25f);
+
+ copy_v3_fl3(v, r, 0.0f, z);
+ setAttrib(vbo, pos_id, vidx++, v);
+ for (int i = 1; i < segments; i++) {
+ float x = cosf(2.f * (float)M_PI * i / segments) * r;
+ float y = sinf(2.f * (float)M_PI * i / segments) * r;
+ copy_v3_fl3(v, x, y, z);
+ setAttrib(vbo, pos_id, vidx++, v);
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+ copy_v3_fl3(v, r, 0.0f, z);
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+
+ for (int j = 0; j < 4; j++) {
+ float x = (((j + 1) % 2) * (j - 1)) * 0.5f;
+ float y = ((j % 2) * (j - 2)) * 0.5f;
+ for (int i = 0; i < 3; i++) {
+ if (i == 1) {
+ x *= 0.5f;
+ y *= 0.5f;
+ }
+
+ float z = 0.25f * i - 0.125f;
+ copy_v3_fl3(v, x, y, z);
+ setAttrib(vbo, pos_id, vidx++, v);
+ if (i == 1) {
+ setAttrib(vbo, pos_id, vidx++, v);
+ }
+ }
+ }
+
+ SHC.drw_speaker = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_speaker;
+}
+
+/* Armature bones */
+static const float bone_octahedral_verts[6][3] = {
+ { 0.0f, 0.0f, 0.0f},
+ { 0.1f, 0.1f, 0.1f},
+ { 0.1f, 0.1f, -0.1f},
+ {-0.1f, 0.1f, -0.1f},
+ {-0.1f, 0.1f, 0.1f},
+ { 0.0f, 1.0f, 0.0f}
+};
+
+static const unsigned int bone_octahedral_wire[24] = {
+ 0, 1, 1, 5, 5, 3, 3, 0,
+ 0, 4, 4, 5, 5, 2, 2, 0,
+ 1, 2, 2, 3, 3, 4, 4, 1,
+};
+
+/* aligned with bone_octahedral_wire
+ * Contains adjacent normal index */
+static const unsigned int bone_octahedral_wire_adjacent_face[24] = {
+ 0, 3, 4, 7, 5, 6, 1, 2,
+ 2, 3, 6, 7, 4, 5, 0, 1,
+ 0, 4, 1, 5, 2, 6, 3, 7,
+};
+
+static const unsigned int bone_octahedral_solid_tris[8][3] = {
+ {2, 1, 0}, /* bottom */
+ {3, 2, 0},
+ {4, 3, 0},
+ {1, 4, 0},
+
+ {5, 1, 2}, /* top */
+ {5, 2, 3},
+ {5, 3, 4},
+ {5, 4, 1}
+};
+
+/* aligned with bone_octahedral_solid_tris */
+static const float bone_octahedral_solid_normals[8][3] = {
+ { M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ {-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
+ {-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
+ { 0.00000000f, -M_SQRT1_2, M_SQRT1_2},
+ { 0.99388373f, 0.11043154f, -0.00000000f},
+ { 0.00000000f, 0.11043154f, -0.99388373f},
+ {-0.99388373f, 0.11043154f, 0.00000000f},
+ { 0.00000000f, 0.11043154f, 0.99388373f}
+};
+
+Batch *DRW_cache_bone_octahedral_get(void)
+{
+ if (!SHC.drw_bone_octahedral) {
+ unsigned int v_idx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, nor_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ /* Vertices */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 24);
+
+ for (int i = 0; i < 8; i++) {
+ setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
+ setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
+ setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
+ setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
+ setAttrib(vbo, nor_id, v_idx, bone_octahedral_solid_normals[i]);
+ setAttrib(vbo, pos_id, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
+ }
+
+ SHC.drw_bone_octahedral = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+ return SHC.drw_bone_octahedral;
+}
+
+Batch *DRW_cache_bone_octahedral_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_octahedral_wire) {
+ unsigned int v_idx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, n1_id, n2_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ n1_id = add_attrib(&format, "N1", COMP_F32, 3, KEEP_FLOAT);
+ n2_id = add_attrib(&format, "N2", COMP_F32, 3, KEEP_FLOAT);
+ }
+
+ /* Vertices */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 12 * 2);
+
+ for (int i = 0; i < 12; i++) {
+ const float *co1 = bone_octahedral_verts[bone_octahedral_wire[i * 2]];
+ const float *co2 = bone_octahedral_verts[bone_octahedral_wire[i * 2 + 1]];
+ const float *n1 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2]];
+ const float *n2 = bone_octahedral_solid_normals[bone_octahedral_wire_adjacent_face[i * 2 + 1]];
+ add_fancy_edge(vbo, pos_id, n1_id, n2_id, &v_idx, co1, co2, n1, n2);
+ }
+
+ SHC.drw_bone_octahedral_wire = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_bone_octahedral_wire;
+}
+
+Batch *DRW_cache_bone_point_get(void)
+{
+ if (!SHC.drw_bone_point) {
+ const int lon_res = 16;
+ const int lat_res = 8;
+ const float rad = 0.05f;
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ unsigned int v_idx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id, nor_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ /* Vertices */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, (lat_res - 1) * lon_res * 6);
+
+ float lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ float lat = 0.0f;
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ if (j != lat_res - 1) { /* Pole */
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon);
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon);
+ }
+
+ if (j != 0) { /* Pole */
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon + lon_inc);
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat + lat_inc, lon + lon_inc);
+ add_lat_lon_vert(vbo, pos_id, nor_id, &v_idx, rad, lat, lon);
+ }
+ }
+ }
+
+ SHC.drw_bone_point = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+ return SHC.drw_bone_point;
+}
+
+Batch *DRW_cache_bone_point_wire_outline_get(void)
+{
+ if (!SHC.drw_bone_point_wire) {
+ VertexBuffer *vbo = sphere_wire_vbo(0.05f);
+ SHC.drw_bone_point_wire = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_bone_point_wire;
+}
+
+Batch *DRW_cache_bone_arrows_get(void)
+{
+ if (!SHC.drw_bone_arrows) {
+ VertexBuffer *vbo = fill_arrows_vbo(0.25f);
+ SHC.drw_bone_arrows = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_bone_arrows;
+}
+
+/* Camera */
+Batch *DRW_cache_camera_get(void)
+{
+ if (!SHC.drw_camera) {
+ float v0 = 0.0f; /* Center point */
+ float v1 = 1.0f; /* + X + Y */
+ float v2 = 2.0f; /* + X - Y */
+ float v3 = 3.0f; /* - X - Y */
+ float v4 = 4.0f; /* - X + Y */
+ float v5 = 5.0f; /* tria + X */
+ float v6 = 6.0f; /* tria - X */
+ float v7 = 7.0f; /* tria + Y */
+ int v_idx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ /* use x coordinate to identify the vertex
+ * the vertex shader take care to place it
+ * appropriatelly */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 1, KEEP_FLOAT);
+ }
+
+ /* Vertices */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 22);
+
+ setAttrib(vbo, pos_id, v_idx++, &v0);
+ setAttrib(vbo, pos_id, v_idx++, &v1);
+
+ setAttrib(vbo, pos_id, v_idx++, &v0);
+ setAttrib(vbo, pos_id, v_idx++, &v2);
+
+ setAttrib(vbo, pos_id, v_idx++, &v0);
+ setAttrib(vbo, pos_id, v_idx++, &v3);
+
+ setAttrib(vbo, pos_id, v_idx++, &v0);
+ setAttrib(vbo, pos_id, v_idx++, &v4);
+
+ /* camera frame */
+ setAttrib(vbo, pos_id, v_idx++, &v1);
+ setAttrib(vbo, pos_id, v_idx++, &v2);
+
+ setAttrib(vbo, pos_id, v_idx++, &v2);
+ setAttrib(vbo, pos_id, v_idx++, &v3);
+
+ setAttrib(vbo, pos_id, v_idx++, &v3);
+ setAttrib(vbo, pos_id, v_idx++, &v4);
+
+ setAttrib(vbo, pos_id, v_idx++, &v4);
+ setAttrib(vbo, pos_id, v_idx++, &v1);
+
+ /* tria */
+ setAttrib(vbo, pos_id, v_idx++, &v5);
+ setAttrib(vbo, pos_id, v_idx++, &v6);
+
+ setAttrib(vbo, pos_id, v_idx++, &v6);
+ setAttrib(vbo, pos_id, v_idx++, &v7);
+
+ setAttrib(vbo, pos_id, v_idx++, &v7);
+ setAttrib(vbo, pos_id, v_idx++, &v5);
+
+ SHC.drw_camera = Batch_create(GL_LINES, vbo, NULL);
+ }
+ return SHC.drw_camera;
+}
+
+Batch *DRW_cache_camera_tria_get(void)
+{
+ if (!SHC.drw_camera_tria) {
+ float v5 = 5.0f; /* tria + X */
+ float v6 = 6.0f; /* tria - X */
+ float v7 = 7.0f; /* tria + Y */
+ int v_idx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ /* use x coordinate to identify the vertex
+ * the vertex shader take care to place it
+ * appropriatelly */
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 1, KEEP_FLOAT);
+ }
+
+ /* Vertices */
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 6);
+
+ /* tria */
+ setAttrib(vbo, pos_id, v_idx++, &v5);
+ setAttrib(vbo, pos_id, v_idx++, &v6);
+ setAttrib(vbo, pos_id, v_idx++, &v7);
+
+ SHC.drw_camera_tria = Batch_create(GL_TRIANGLES, vbo, NULL);
+ }
+ return SHC.drw_camera_tria;
+}
/* Object Center */
Batch *DRW_cache_single_vert_get(void)
@@ -509,19 +1243,24 @@ Batch *DRW_cache_single_vert_get(void)
}
/* Meshes */
-Batch *DRW_cache_wire_overlay_get(Object *ob)
+void DRW_cache_wire_overlay_get(Object *ob, Batch **tris, Batch **ledges, Batch **lverts)
{
- Batch *overlay_wire = NULL;
+ BLI_assert(ob->type == OB_MESH);
+ Mesh *me = ob->data;
+
+ *tris = BKE_mesh_batch_cache_get_overlay_triangles(me);
+ *ledges = BKE_mesh_batch_cache_get_overlay_loose_edges(me);
+ *lverts = BKE_mesh_batch_cache_get_overlay_loose_verts(me);
+}
+
+Batch *DRW_cache_face_centers_get(Object *ob)
+{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
-#if 1 /* new version not working */
- overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me);
-#else
- overlay_wire = BKE_mesh_batch_cache_get_all_edges(me);
-#endif
- return overlay_wire;
+
+ return BKE_mesh_batch_cache_get_overlay_facedots(me);
}
Batch *DRW_cache_wire_outline_get(Object *ob)
@@ -543,7 +1282,31 @@ Batch *DRW_cache_surface_get(Object *ob)
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
- surface = BKE_mesh_batch_cache_get_all_triangles(me);
+ surface = BKE_mesh_batch_cache_get_triangles_with_normals(me);
+
+ return surface;
+}
+
+Batch *DRW_cache_surface_verts_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ surface = BKE_mesh_batch_cache_get_points_with_normals(me);
+
+ return surface;
+}
+
+Batch *DRW_cache_verts_get(Object *ob)
+{
+ Batch *surface = NULL;
+
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ surface = BKE_mesh_batch_cache_get_all_verts(me);
return surface;
}
@@ -553,4 +1316,4 @@ struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
/* TODO */
return NULL;
}
-#endif \ No newline at end of file
+#endif
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 0e467bddbfa..0af7f3d08b1 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -35,23 +35,48 @@ void DRW_shape_cache_free(void);
struct Batch *DRW_cache_fullscreen_quad_get(void);
struct Batch *DRW_cache_single_vert_get(void);
struct Batch *DRW_cache_single_line_get(void);
+struct Batch *DRW_cache_single_line_endpoints_get(void);
/* Empties */
struct Batch *DRW_cache_plain_axes_get(void);
struct Batch *DRW_cache_single_arrow_get(void);
struct Batch *DRW_cache_cube_get(void);
struct Batch *DRW_cache_circle_get(void);
+struct Batch *DRW_cache_square_get(void);
struct Batch *DRW_cache_empty_sphere_get(void);
struct Batch *DRW_cache_empty_cone_get(void);
struct Batch *DRW_cache_arrows_get(void);
+struct Batch *DRW_cache_axis_names_get(void);
/* Lamps */
struct Batch *DRW_cache_lamp_get(void);
struct Batch *DRW_cache_lamp_sunrays_get(void);
+struct Batch *DRW_cache_lamp_area_get(void);
+struct Batch *DRW_cache_lamp_hemi_get(void);
+struct Batch *DRW_cache_lamp_spot_get(void);
+struct Batch *DRW_cache_lamp_spot_square_get(void);
+
+/* Camera */
+struct Batch *DRW_cache_camera_get(void);
+struct Batch *DRW_cache_camera_tria_get(void);
+
+/* Speaker */
+struct Batch *DRW_cache_speaker_get(void);
+
+/* Bones */
+struct Batch *DRW_cache_bone_octahedral_get(void);
+struct Batch *DRW_cache_bone_octahedral_wire_outline_get(void);
+struct Batch *DRW_cache_bone_point_get(void);
+struct Batch *DRW_cache_bone_point_wire_outline_get(void);
+struct Batch *DRW_cache_bone_arrows_get(void);
/* Meshes */
-struct Batch *DRW_cache_wire_overlay_get(struct Object *ob);
+void DRW_cache_wire_overlay_get(
+ struct Object *ob, struct Batch **tris, struct Batch **ledges, struct Batch **lverts);
+struct Batch *DRW_cache_face_centers_get(struct Object *ob);
struct Batch *DRW_cache_wire_outline_get(struct Object *ob);
struct Batch *DRW_cache_surface_get(struct Object *ob);
+struct Batch *DRW_cache_surface_verts_get(struct Object *ob);
+struct Batch *DRW_cache_verts_get(struct Object *ob);
#endif /* __DRAW_CACHE_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
new file mode 100644
index 00000000000..0ec2ed67ca2
--- /dev/null
+++ b/source/blender/draw/intern/draw_common.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_common.c
+ * \ingroup draw
+ */
+
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+
+#include "draw_common.h"
+
+/* Colors & Constant */
+GlobalsUboStorage ts;
+struct GPUUniformBuffer *globals_ubo = NULL;
+
+void DRW_globals_update(void)
+{
+ UI_GetThemeColor4fv(TH_WIRE, ts.colorWire);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, ts.colorWireEdit);
+ UI_GetThemeColor4fv(TH_ACTIVE, ts.colorActive);
+ UI_GetThemeColor4fv(TH_SELECT, ts.colorSelect);
+ UI_GetThemeColor4fv(TH_TRANSFORM, ts.colorTransform);
+ UI_GetThemeColor4fv(TH_GROUP_ACTIVE, ts.colorGroupActive);
+ UI_GetThemeColor4fv(TH_GROUP, ts.colorGroup);
+ UI_GetThemeColor4fv(TH_LAMP, ts.colorLamp);
+ UI_GetThemeColor4fv(TH_SPEAKER, ts.colorSpeaker);
+ UI_GetThemeColor4fv(TH_CAMERA, ts.colorCamera);
+ UI_GetThemeColor4fv(TH_EMPTY, ts.colorEmpty);
+ UI_GetThemeColor4fv(TH_VERTEX, ts.colorVertex);
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, ts.colorVertexSelect);
+ UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, ts.colorEditMeshActive);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, ts.colorEdgeSelect);
+ UI_GetThemeColor4fv(TH_EDGE_SEAM, ts.colorEdgeSeam);
+ UI_GetThemeColor4fv(TH_EDGE_SHARP, ts.colorEdgeSharp);
+ UI_GetThemeColor4fv(TH_EDGE_CREASE, ts.colorEdgeCrease);
+ UI_GetThemeColor4fv(TH_EDGE_BEVEL, ts.colorEdgeBWeight);
+ UI_GetThemeColor4fv(TH_EDGE_FACESEL, ts.colorEdgeFaceSelect);
+ UI_GetThemeColor4fv(TH_FACE, ts.colorFace);
+ UI_GetThemeColor4fv(TH_FACE_SELECT, ts.colorFaceSelect);
+ UI_GetThemeColor4fv(TH_NORMAL, ts.colorNormal);
+ UI_GetThemeColor4fv(TH_VNORMAL, ts.colorVNormal);
+ UI_GetThemeColor4fv(TH_LNORMAL, ts.colorLNormal);
+ UI_GetThemeColor4fv(TH_FACE_DOT, ts.colorFaceDot);
+ UI_GetThemeColor4fv(TH_BACK, ts.colorBackground);
+
+ /* Grid */
+ UI_GetThemeColorShade4fv(TH_GRID, 10, ts.colorGrid);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetThemeColorShade4fv(TH_GRID,
+ (ts.colorGrid[0] + ts.colorGrid[1] + ts.colorGrid[2] + 0.12 >
+ ts.colorBackground[0] + ts.colorBackground[1] + ts.colorBackground[2])
+ ? 20 : -10, ts.colorGridEmphasise);
+ /* Grid Axis */
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_X, 0.5f, -10, ts.colorGridAxisX);
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Y, 0.5f, -10, ts.colorGridAxisY);
+ UI_GetThemeColorBlendShade4fv(TH_GRID, TH_AXIS_Z, 0.5f, -10, ts.colorGridAxisZ);
+
+ UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, ts.colorDeselect);
+ UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, ts.colorOutline);
+ UI_GetThemeColorShadeAlpha4fv(TH_LAMP, 0, 255, ts.colorLampNoAlpha);
+
+ ts.sizeLampCenter = (U.obcenter_dia + 1.5f) * U.pixelsize;
+ ts.sizeLampCircle = U.pixelsize * 9.0f;
+ ts.sizeLampCircleShadow = ts.sizeLampCircle + U.pixelsize * 3.0f;
+
+ /* M_SQRT2 to be at least the same size of the old square */
+ ts.sizeVertex = UI_GetThemeValuef(TH_VERTEX_SIZE) * M_SQRT2 / 2.0f;
+ ts.sizeFaceDot = UI_GetThemeValuef(TH_FACEDOT_SIZE) * M_SQRT2;
+ ts.sizeEdge = 1.0f / 2.0f; /* TODO Theme */
+ ts.sizeEdgeFix = 0.5f + 2.0f * (2.0f * (MAX2(ts.sizeVertex, ts.sizeEdge)) * M_SQRT1_2);
+
+ /* TODO Waiting for notifiers to invalidate cache */
+ if (globals_ubo) {
+ DRW_uniformbuffer_free(globals_ubo);
+ }
+
+ globals_ubo = DRW_uniformbuffer_create(sizeof(GlobalsUboStorage), &ts);
+}
+
+/* ********************************* SHGROUP ************************************* */
+
+DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_uniform_float(grp, "size", size, 1);
+ DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
+
+ DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+ DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "world_pos", 3);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_uniform_float(grp, "size", size, 1);
+ DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_objspace_solid(DRWPass *pass, struct Batch *geom, float (*obmat)[4])
+{
+ static float light[3] = {0.0f, 0.0f, 1.0f};
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_uniform_mat4(grp, "ModelMatrix", (float *)obmat);
+ DRW_shgroup_uniform_vec3(grp, "light", light, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_objspace_wire(DRWPass *pass, struct Batch *geom, float (*obmat)[4])
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_attrib_float(grp, "color", 4);
+ DRW_shgroup_uniform_mat4(grp, "ModelMatrix", (float *)obmat);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance_axis_names(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "size", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_camera_instance(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_CAMERA);
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "corners", 8);
+ DRW_shgroup_attrib_float(grp, "depth", 1);
+ DRW_shgroup_attrib_float(grp, "tria", 4);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_distance_lines_instance(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_DISTANCE_LINES);
+ static float point_size = 4.0f;
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "start", 1);
+ DRW_shgroup_attrib_float(grp, "end", 1);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_float(grp, "size", &point_size, 1);
+
+ return grp;
+}
+
+DRWShadingGroup *shgroup_spot_instance(DRWPass *pass, struct Batch *geom)
+{
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR);
+ static bool True = true;
+ static bool False = false;
+
+ DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
+ DRW_shgroup_attrib_float(grp, "color", 3);
+ DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
+ DRW_shgroup_uniform_bool(grp, "drawFront", &False, 1);
+ DRW_shgroup_uniform_bool(grp, "drawBack", &False, 1);
+ DRW_shgroup_uniform_bool(grp, "drawSilhouette", &True, 1);
+
+ return grp;
+}
+
+/* ******************************************** WIRES *********************************************** */
+
+/* TODO FINISH */
+/* Get the wire color theme_id of an object based on it's state
+ * **color is a way to get a pointer to the static color var associated */
+int DRW_object_wire_theme_get(Object *ob, SceneLayer *sl, float **color)
+{
+ const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
+ /* confusing logic here, there are 2 methods of setting the color
+ * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
+ *
+ * note: no theme yet for 'colindex' */
+ int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
+
+ if (//(scene->obedit == NULL) &&
+ ((G.moving & G_TRANSFORM_OBJ) != 0) &&
+ ((ob->base_flag & BASE_SELECTED) != 0))
+ {
+ theme_id = TH_TRANSFORM;
+ }
+ else {
+ /* Sets the 'theme_id' or fallback to wire */
+ if ((ob->flag & OB_FROMGROUP) != 0) {
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ /* uses darker active color for non-active + selected */
+ theme_id = TH_GROUP_ACTIVE;
+
+ // if (sl->basact->object != ob) {
+ // theme_shade = -16;
+ // }
+ }
+ else {
+ theme_id = TH_GROUP;
+ }
+ }
+ else {
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ theme_id = (sl->basact && sl->basact->object == ob) ? TH_ACTIVE : TH_SELECT;
+ }
+ else {
+ if (ob->type == OB_LAMP) theme_id = TH_LAMP;
+ else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
+ else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
+ else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
+ /* fallback to TH_WIRE */
+ }
+ }
+ }
+
+ if (color != NULL) {
+ switch (theme_id) {
+ case TH_WIRE_EDIT: *color = ts.colorTransform; break;
+ case TH_ACTIVE: *color = ts.colorActive; break;
+ case TH_SELECT: *color = ts.colorSelect; break;
+ case TH_GROUP: *color = ts.colorGroup; break;
+ case TH_GROUP_ACTIVE: *color = ts.colorGroupActive; break;
+ case TH_TRANSFORM: *color = ts.colorTransform; break;
+ case OB_SPEAKER: *color = ts.colorSpeaker; break;
+ case OB_CAMERA: *color = ts.colorCamera; break;
+ case OB_EMPTY: *color = ts.colorEmpty; break;
+ case OB_LAMP: *color = ts.colorLamp; break;
+ default: *color = ts.colorWire; break;
+ }
+ }
+
+ return theme_id;
+}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
new file mode 100644
index 00000000000..e8e7cf40432
--- /dev/null
+++ b/source/blender/draw/intern/draw_common.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_common.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_COMMON__
+#define __DRAW_COMMON__
+
+struct DRWPass;
+struct DRWShadingGroup;
+struct Batch;
+struct Object;
+struct SceneLayer;
+
+/* Used as ubo but colors can be directly
+ * referenced as well */
+/* Keep in sync with globalsBlock in shaders */
+typedef struct GlobalsUboStorage {
+ /* UBOs data needs to be 16 byte aligned (size of vec4) */
+ float colorWire[4];
+ float colorWireEdit[4];
+ float colorActive[4];
+ float colorSelect[4];
+ float colorTransform[4];
+ float colorGroupActive[4];
+ float colorGroup[4];
+ float colorLamp[4];
+ float colorSpeaker[4];
+ float colorCamera[4];
+ float colorEmpty[4];
+ float colorVertex[4];
+ float colorVertexSelect[4];
+ float colorEditMeshActive[4];
+ float colorEdgeSelect[4];
+ float colorEdgeSeam[4];
+ float colorEdgeSharp[4];
+ float colorEdgeCrease[4];
+ float colorEdgeBWeight[4];
+ float colorEdgeFaceSelect[4];
+ float colorFace[4];
+ float colorFaceSelect[4];
+ float colorNormal[4];
+ float colorVNormal[4];
+ float colorLNormal[4];
+ float colorFaceDot[4];
+
+ float colorDeselect[4];
+ float colorOutline[4];
+ float colorLampNoAlpha[4];
+
+ float colorBackground[4];
+
+ float colorGrid[4];
+ float colorGridEmphasise[4];
+ float colorGridAxisX[4];
+ float colorGridAxisY[4];
+ float colorGridAxisZ[4];
+
+ /* Pack individual float at the end of the buffer to avoid alignement errors */
+ float sizeLampCenter, sizeLampCircle, sizeLampCircleShadow;
+ float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
+ float gridDistance, gridResolution, gridSubdivisions, gridScale;
+} GlobalsUboStorage;
+/* Keep in sync with globalsBlock in shaders */
+
+void DRW_globals_update(void);
+
+struct DRWShadingGroup *shgroup_dynlines_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_dynpoints_uniform_color(struct DRWPass *pass, float color[4], float *size);
+struct DRWShadingGroup *shgroup_groundlines_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_groundpoints_uniform_color(struct DRWPass *pass, float color[4]);
+struct DRWShadingGroup *shgroup_instance_screenspace(struct DRWPass *pass, struct Batch *geom, float *size);
+struct DRWShadingGroup *shgroup_instance_objspace_solid(struct DRWPass *pass, struct Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_objspace_wire(struct DRWPass *pass, struct Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_axis_names(struct DRWPass *pass, struct Batch *geom);
+struct DRWShadingGroup *shgroup_instance(struct DRWPass *pass, struct Batch *geom);
+struct DRWShadingGroup *shgroup_camera_instance(struct DRWPass *pass, struct Batch *geom);
+struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, struct Batch *geom);
+struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Batch *geom);
+
+int DRW_object_wire_theme_get(struct Object *ob, struct SceneLayer *sl, float **color);
+
+/* draw_armature.c */
+void DRW_shgroup_armature_object(
+ struct Object *ob, struct SceneLayer *sl, struct DRWPass *pass_bone_solid,
+ struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines);
+
+void DRW_shgroup_armature_pose(
+ struct Object *ob, struct DRWPass *pass_bone_solid,
+ struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines);
+
+void DRW_shgroup_armature_edit(
+ struct Object *ob, struct DRWPass *pass_bone_solid,
+ struct DRWPass *pass_bone_wire, struct DRWShadingGroup *shgrp_relationship_lines);
+
+#endif /* __DRAW_COMMON__ */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 970bd2f6dee..d2d98f15fa9 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -19,12 +19,13 @@
*
*/
-/** \file blender/draw/draw_manager.c
+/** \file blender/draw/intern/draw_manager.c
* \ingroup draw
*/
#include <stdio.h>
+#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_string.h"
@@ -34,35 +35,43 @@
#include "BKE_global.h"
#include "BLT_translation.h"
+#include "BLF_api.h"
#include "DRW_engine.h"
#include "DRW_render.h"
#include "DNA_view3d_types.h"
+#include "DNA_screen_types.h"
+
+#include "ED_space_api.h"
+#include "ED_screen.h"
-#include "GPU_basic_shader.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
-#include "GPU_immediate.h"
-#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
#include "GPU_viewport.h"
+#include "GPU_matrix.h"
+
+#include "PIL_time.h"
#include "RE_engine.h"
#include "UI_resources.h"
+#include "draw_mode_engines.h"
#include "clay.h"
+#include "eevee.h"
#define MAX_ATTRIB_NAME 32
+#define MAX_PASS_NAME 32
extern char datatoc_gpu_shader_2D_vert_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
-extern char datatoc_gpu_shader_basic_vert_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
/* Structures */
typedef enum {
@@ -81,7 +90,7 @@ typedef enum {
DRW_ATTRIB_FLOAT,
} DRWAttribType;
-typedef struct DRWUniform {
+struct DRWUniform {
struct DRWUniform *next, *prev;
DRWUniformType type;
int location;
@@ -89,7 +98,7 @@ typedef struct DRWUniform {
int arraysize;
int bindloc;
const void *value;
-} DRWUniform;
+};
typedef struct DRWAttrib {
struct DRWAttrib *next, *prev;
@@ -108,11 +117,14 @@ struct DRWInterface {
int attribs_size[16];
int attribs_loc[16];
/* matrices locations */
+ int model;
int modelview;
int projection;
+ int view;
int modelviewprojection;
int viewprojection;
int normal;
+ int worldnormal;
int eye;
/* Dynamic batch */
GLuint instance_vbo;
@@ -123,7 +135,13 @@ struct DRWInterface {
struct DRWPass {
ListBase shgroups; /* DRWShadingGroup */
DRWState state;
- float state_param; /* Line / Point width */
+ char name[MAX_PASS_NAME];
+ /* use two query to not stall the cpu waiting for queries to complete */
+ unsigned int timer_queries[2];
+ /* alternate between front and back query */
+ unsigned int front_idx;
+ unsigned int back_idx;
+ bool wasdrawn; /* if it was drawn during this frame */
};
typedef struct DRWCall {
@@ -143,7 +161,7 @@ struct DRWShadingGroup {
struct GPUShader *shader; /* Shader to bind */
struct DRWInterface *interface; /* Uniforms pointers */
ListBase calls; /* DRWCall or DRWDynamicCall depending of type*/
- int state; /* State changes for this batch only */
+ DRWState state; /* State changes for this batch only */
int type;
Batch *instance_geom; /* Geometry to instance */
@@ -158,22 +176,33 @@ enum {
DRW_SHG_INSTANCE,
};
+/* only 16 bits long */
+enum {
+ STENCIL_SELECT = (1 << 0),
+ STENCIL_ACTIVE = (1 << 1),
+};
+
/* Render State */
-static struct DRWGlobalState{
+static struct DRWGlobalState {
+ /* Rendering state */
GPUShader *shader;
- struct GPUFrameBuffer *default_framebuffer;
- FramebufferList *current_fbl;
- TextureList *current_txl;
- PassList *current_psl;
ListBase bound_texs;
int tex_bind_id;
+
+ /* Per viewport */
+ GPUViewport *viewport;
+ struct GPUFrameBuffer *default_framebuffer;
float size[2];
float screenvecs[2][3];
float pixsize;
- /* Current rendering context set by DRW_viewport_init */
+
+ /* Current rendering context */
const struct bContext *context;
+ ListBase enabled_engines; /* RenderEngineType */
} DST = {NULL};
+ListBase DRW_engines = {NULL, NULL};
+
/* ***************************************** TEXTURES ******************************************/
static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels)
{
@@ -183,13 +212,13 @@ static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *da
case DRW_TEX_RG_16: *data_type = GPU_RG16F; break;
case DRW_TEX_RG_32: *data_type = GPU_RG32F; break;
case DRW_TEX_R_8: *data_type = GPU_R8; break;
+ case DRW_TEX_R_16: *data_type = GPU_R16F; break;
#if 0
case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break;
case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break;
case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break;
case DRW_TEX_RG_8: *data_type = GPU_RG8; break;
- case DRW_TEX_R_16: *data_type = GPU_R16F; break;
case DRW_TEX_R_32: *data_type = GPU_R32F; break;
#endif
case DRW_TEX_DEPTH_16: *data_type = GPU_DEPTH_COMPONENT16; break;
@@ -299,6 +328,44 @@ GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *fra
return GPU_shader_create(vert, frag, geom, NULL, defines, 0, 0, 0);
}
+GPUShader *DRW_shader_create_with_lib(const char *vert, const char *geom, const char *frag, const char *lib, const char *defines)
+{
+ GPUShader *sh;
+ char *vert_with_lib = NULL;
+ char *frag_with_lib = NULL;
+ char *geom_with_lib = NULL;
+
+ DynStr *ds_vert = BLI_dynstr_new();
+ BLI_dynstr_append(ds_vert, lib);
+ BLI_dynstr_append(ds_vert, vert);
+ vert_with_lib = BLI_dynstr_get_cstring(ds_vert);
+ BLI_dynstr_free(ds_vert);
+
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, lib);
+ BLI_dynstr_append(ds_frag, frag);
+ frag_with_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+
+ if (geom) {
+ DynStr *ds_geom = BLI_dynstr_new();
+ BLI_dynstr_append(ds_geom, lib);
+ BLI_dynstr_append(ds_geom, geom);
+ geom_with_lib = BLI_dynstr_get_cstring(ds_geom);
+ BLI_dynstr_free(ds_geom);
+ }
+
+ sh = GPU_shader_create(vert_with_lib, frag_with_lib, geom_with_lib, NULL, defines, 0, 0, 0);
+
+ MEM_freeN(vert_with_lib);
+ MEM_freeN(frag_with_lib);
+ if (geom) {
+ MEM_freeN(geom_with_lib);
+ }
+
+ return sh;
+}
+
GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
{
return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
@@ -309,6 +376,11 @@ GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
}
+GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
+{
+ return GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
GPUShader *DRW_shader_create_3D_depth_only(void)
{
return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
@@ -325,11 +397,14 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
{
DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
+ interface->model = GPU_shader_get_uniform(shader, "ModelMatrix");
interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix");
interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix");
+ interface->view = GPU_shader_get_uniform(shader, "ViewMatrix");
interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix");
interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
+ interface->worldnormal = GPU_shader_get_uniform(shader, "WorldNormalMatrix");
interface->eye = GPU_shader_get_uniform(shader, "eye");
interface->instance_count = 0;
interface->attribs_count = 0;
@@ -457,7 +532,11 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
BLI_freelistN(&shgroup->calls);
BLI_freelistN(&shgroup->interface->uniforms);
BLI_freelistN(&shgroup->interface->attribs);
- /* TODO free instance vbo */
+
+ if (shgroup->interface->instance_vbo) {
+ glDeleteBuffers(1, &shgroup->interface->instance_vbo);
+ }
+
MEM_freeN(shgroup->interface);
if (shgroup->batch_geom) {
@@ -467,14 +546,14 @@ void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[4])
{
- if (geom) {
- DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
+ BLI_assert(geom != NULL);
- call->obmat = obmat;
- call->geometry = geom;
+ DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
- BLI_addtail(&shgroup->calls, call);
- }
+ call->obmat = obmat;
+ call->geometry = geom;
+
+ BLI_addtail(&shgroup->calls, call);
}
void DRW_shgroup_dynamic_call_add(DRWShadingGroup *shgroup, ...)
@@ -519,10 +598,9 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const
DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 0, loc);
}
-void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc)
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex, int loc)
{
- /* we abuse the lenght attrib to store the buffer index */
- DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, NULL, value, 0, loc);
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, tex, 0, 0, loc);
}
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize)
@@ -672,9 +750,12 @@ static void shgroup_dynamic_instance(DRWShadingGroup *shgroup)
static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
{
-#ifdef WITH_VIEWPORT_CACHE_TEST
- if (shgroup->interface->instance_vbo || shgroup->batch_geom) return;
-#endif
+ if ((shgroup->interface->instance_vbo || shgroup->batch_geom) &&
+ (G.debug_value == 667))
+ {
+ return;
+ }
+
if (shgroup->type == DRW_SHG_INSTANCE) {
shgroup_dynamic_instance(shgroup);
}
@@ -689,6 +770,7 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
{
DRWPass *pass = MEM_callocN(sizeof(DRWPass), name);
pass->state = state;
+ BLI_strncpy(pass->name, name, MAX_PASS_NAME);
BLI_listbase_clear(&pass->shgroups);
@@ -700,87 +782,136 @@ void DRW_pass_free(DRWPass *pass)
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
DRW_shgroup_free(shgroup);
}
+
+ glDeleteQueries(2, pass->timer_queries);
BLI_freelistN(&pass->shgroups);
}
/* ****************************************** DRAW ******************************************/
-void DRW_draw_background(void)
+#ifdef WITH_CLAY_ENGINE
+static void set_state(DRWState flag, const bool reset)
{
- /* Just to make sure */
- glDepthMask(GL_TRUE);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- /* Gradient background Color */
- gpuMatrixBegin3D(); /* TODO: finish 2D API */
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
- unsigned char col_hi[3], col_lo[3];
+ /* TODO Keep track of the state and only revert what is needed */
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ if (reset) {
+ /* Depth Write */
+ if (flag & DRW_STATE_WRITE_DEPTH)
+ glDepthMask(GL_TRUE);
+ else
+ glDepthMask(GL_FALSE);
+
+ /* Color Write */
+ if (flag & DRW_STATE_WRITE_COLOR)
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ else
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* Backface Culling */
+ if (flag & DRW_STATE_CULL_BACK ||
+ flag & DRW_STATE_CULL_FRONT)
+ {
+ glEnable(GL_CULL_FACE);
- UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
- UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+ if (flag & DRW_STATE_CULL_BACK)
+ glCullFace(GL_BACK);
+ else if (flag & DRW_STATE_CULL_FRONT)
+ glCullFace(GL_FRONT);
+ }
+ else {
+ glDisable(GL_CULL_FACE);
+ }
- immBegin(GL_QUADS, 4);
- immAttrib3ubv(color, col_lo);
- immVertex2f(pos, -1.0f, -1.0f);
- immVertex2f(pos, 1.0f, -1.0f);
+ /* Depht Test */
+ if (flag & (DRW_STATE_DEPTH_LESS | DRW_STATE_DEPTH_EQUAL | DRW_STATE_DEPTH_GREATER))
+ {
+ glEnable(GL_DEPTH_TEST);
+
+ if (flag & DRW_STATE_DEPTH_LESS)
+ glDepthFunc(GL_LEQUAL);
+ else if (flag & DRW_STATE_DEPTH_EQUAL)
+ glDepthFunc(GL_EQUAL);
+ else if (flag & DRW_STATE_DEPTH_GREATER)
+ glDepthFunc(GL_GREATER);
+ }
+ else {
+ glDisable(GL_DEPTH_TEST);
+ }
+ }
- immAttrib3ubv(color, col_hi);
- immVertex2f(pos, 1.0f, 1.0f);
- immVertex2f(pos, -1.0f, 1.0f);
- immEnd();
+ /* Wire Width */
+ if (flag & DRW_STATE_WIRE) {
+ glLineWidth(1.0f);
+ }
+ else if (flag & DRW_STATE_WIRE_LARGE) {
+ glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+ }
- immUnbindProgram();
+ /* Points Size */
+ if (flag & DRW_STATE_POINT) {
+ GPU_enable_program_point_size();
+ glPointSize(5.0f);
+ }
+ else if (reset) {
+ GPU_disable_program_point_size();
+ }
- gpuMatrixEnd();
+ /* Blending (all buffer) */
+ if (flag & DRW_STATE_BLEND) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- else {
- /* Solid background Color */
- UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ else if (reset) {
+ glDisable(GL_BLEND);
}
-}
-#ifdef WITH_CLAY_ENGINE
-/* Only alter the state (does not reset it like set_state() ) */
-static void shgroup_set_state(DRWShadingGroup *shgroup)
-{
- if (shgroup->state) {
- /* Blend */
- if (shgroup->state & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
- }
- /* Wire width */
- if (shgroup->state & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
- }
- else if (shgroup->state & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
+ /* Line Stipple */
+ if (flag & DRW_STATE_STIPPLE_2) {
+ setlinestyle(2);
+ }
+ else if (flag & DRW_STATE_STIPPLE_3) {
+ setlinestyle(3);
+ }
+ else if (flag & DRW_STATE_STIPPLE_4) {
+ setlinestyle(4);
+ }
+ else if (reset) {
+ setlinestyle(0);
+ }
- /* Line Stipple */
- if (shgroup->state & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
+ /* Stencil */
+ if (flag & (DRW_STATE_WRITE_STENCIL_SELECT | DRW_STATE_WRITE_STENCIL_ACTIVE |
+ DRW_STATE_TEST_STENCIL_SELECT | DRW_STATE_TEST_STENCIL_ACTIVE))
+ {
+ glEnable(GL_STENCIL_TEST);
+
+ /* Stencil Write */
+ if (flag & DRW_STATE_WRITE_STENCIL_SELECT) {
+ glStencilMask(STENCIL_SELECT);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_SELECT);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
+ else if (flag & DRW_STATE_WRITE_STENCIL_ACTIVE) {
+ glStencilMask(STENCIL_ACTIVE);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+ glStencilFunc(GL_ALWAYS, 0xFF, STENCIL_ACTIVE);
}
- else if (shgroup->state & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
+ /* Stencil Test */
+ else if (flag & DRW_STATE_TEST_STENCIL_SELECT) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_SELECT);
}
-
- if (shgroup->state & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
+ else if (flag & DRW_STATE_TEST_STENCIL_ACTIVE) {
+ glStencilMask(0x00); /* disable write */
+ glStencilFunc(GL_NOTEQUAL, 0xFF, STENCIL_ACTIVE);
}
}
+ else if (reset) {
+ /* disable write & test */
+ glStencilMask(0x00);
+ glStencilFunc(GL_ALWAYS, 1, 0xFF);
+ glDisable(GL_STENCIL_TEST);
+ }
}
typedef struct DRWBoundTexture {
@@ -792,13 +923,14 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
{
RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
DRWInterface *interface = shgroup->interface;
-
- float mvp[4][4], mv[4][4], n[3][3];
+
+ float mvp[4][4], mv[4][4], n[3][3], wn[3][3];
float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
bool do_mvp = (interface->modelviewprojection != -1);
bool do_mv = (interface->modelview != -1);
bool do_n = (interface->normal != -1);
+ bool do_wn = (interface->worldnormal != -1);
bool do_eye = (interface->eye != -1);
if (do_mvp) {
@@ -812,6 +944,11 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
invert_m3(n);
transpose_m3(n);
}
+ if (do_wn) {
+ copy_m3_m4(wn, obmat);
+ invert_m3(wn);
+ transpose_m3(wn);
+ }
if (do_eye) {
/* Used by orthographic wires */
float tmp[3][3];
@@ -822,6 +959,9 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
/* Should be really simple */
/* step 1 : bind object dependent matrices */
+ if (interface->model != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->model, 16, 1, (float *)obmat);
+ }
if (interface->modelviewprojection != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
}
@@ -831,12 +971,18 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o
if (interface->projection != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat);
}
+ if (interface->view != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->view, 16, 1, (float *)rv3d->viewmat);
+ }
if (interface->modelview != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
}
if (interface->normal != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
}
+ if (interface->worldnormal != -1) {
+ GPU_shader_uniform_vector(shgroup->shader, interface->worldnormal, 9, 1, (float *)wn);
+ }
if (interface->eye != -1) {
GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
}
@@ -858,6 +1004,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
BLI_assert(shgroup->interface);
DRWInterface *interface = shgroup->interface;
+ GPUTexture *tex;
if (DST.shader != shgroup->shader) {
if (DST.shader) GPU_shader_unbind();
@@ -869,7 +1016,9 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
shgroup_dynamic_batch_from_calls(shgroup);
}
- shgroup_set_state(shgroup);
+ if (shgroup->state != 0) {
+ set_state(shgroup->state, false);
+ }
/* Binding Uniform */
/* Don't check anything, Interface should already contain the least uniform as possible */
@@ -887,25 +1036,26 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
GPU_shader_uniform_vector(shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
break;
case DRW_UNIFORM_TEXTURE:
- GPU_texture_bind((GPUTexture *)uni->value, uni->bindloc);
+ tex = (GPUTexture *)uni->value;
+ GPU_texture_bind(tex, uni->bindloc);
bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
- bound_tex->tex = (GPUTexture *)uni->value;
+ bound_tex->tex = tex;
BLI_addtail(&DST.bound_texs, bound_tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, (GPUTexture *)uni->value);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BUFFER:
- /* restore index from lenght we abused */
- GPU_texture_bind(DST.current_txl->textures[uni->length], uni->bindloc);
- GPU_texture_compare_mode(DST.current_txl->textures[uni->length], false);
- GPU_texture_filter_mode(DST.current_txl->textures[uni->length], false);
-
+ tex = *((GPUTexture **)uni->value);
+ GPU_texture_bind(tex, uni->bindloc);
+ GPU_texture_compare_mode(tex, false);
+ GPU_texture_filter_mode(tex, false);
+
bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
- bound_tex->tex = DST.current_txl->textures[uni->length];
+ bound_tex->tex = tex;
BLI_addtail(&DST.bound_texs, bound_tex);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, DST.current_txl->textures[uni->length]);
+ GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
break;
case DRW_UNIFORM_BLOCK:
GPU_uniformbuffer_bind((GPUUniformBuffer *)uni->value, uni->bindloc);
@@ -937,100 +1087,37 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
}
}
-static void set_state(short flag)
+void DRW_draw_pass(DRWPass *pass)
{
- /* TODO Keep track of the state and only revert what is needed */
-
- /* Depth Write */
- if (flag & DRW_STATE_WRITE_DEPTH)
- glDepthMask(GL_TRUE);
- else
- glDepthMask(GL_FALSE);
-
- /* Color Write */
- if (flag & DRW_STATE_WRITE_COLOR)
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- else
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- /* Backface Culling */
- if (flag & DRW_STATE_CULL_BACK ||
- flag & DRW_STATE_CULL_FRONT) {
-
- glEnable(GL_CULL_FACE);
-
- if (flag & DRW_STATE_CULL_BACK)
- glCullFace(GL_BACK);
- else if (flag & DRW_STATE_CULL_FRONT)
- glCullFace(GL_FRONT);
- }
- else {
- glDisable(GL_CULL_FACE);
- }
-
- /* Depht Test */
- if (flag & DRW_STATE_DEPTH_LESS ||
- flag & DRW_STATE_DEPTH_EQUAL) {
+ /* Start fresh */
+ DST.shader = NULL;
+ DST.tex_bind_id = 0;
- glEnable(GL_DEPTH_TEST);
+ set_state(pass->state, true);
+ BLI_listbase_clear(&DST.bound_texs);
- if (flag & DRW_STATE_DEPTH_LESS)
- glDepthFunc(GL_LEQUAL);
- else if (flag & DRW_STATE_DEPTH_EQUAL)
- glDepthFunc(GL_EQUAL);
- }
- else {
- glDisable(GL_DEPTH_TEST);
- }
+ pass->wasdrawn = true;
- /* Wire Width */
- if (flag & DRW_STATE_WIRE) {
- glLineWidth(1.0f);
- }
- else if (flag & DRW_STATE_WIRE_LARGE) {
- glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- }
-
- /* Points Size */
- if (flag & DRW_STATE_POINT) {
- GPU_enable_program_point_size();
- glPointSize(5.0f);
- }
- else {
- GPU_disable_program_point_size();
- }
+ /* Init Timer queries */
+ if (pass->timer_queries[0] == 0) {
+ pass->front_idx = 0;
+ pass->back_idx = 1;
- /* Blending (all buffer) */
- if (flag & DRW_STATE_BLEND) {
- glEnable(GL_BLEND);
- }
- else {
- glDisable(GL_BLEND);
- }
+ glGenQueries(2, pass->timer_queries);
- /* Line Stipple */
- if (flag & DRW_STATE_STIPPLE_2) {
- setlinestyle(2);
- }
- else if (flag & DRW_STATE_STIPPLE_3) {
- setlinestyle(3);
- }
- else if (flag & DRW_STATE_STIPPLE_4) {
- setlinestyle(4);
+ /* dummy query, avoid gl error */
+ glBeginQuery(GL_TIME_ELAPSED, pass->timer_queries[pass->front_idx]);
+ glEndQuery(GL_TIME_ELAPSED);
}
else {
- setlinestyle(0);
+ /* swap indices */
+ unsigned int tmp = pass->back_idx;
+ pass->back_idx = pass->front_idx;
+ pass->front_idx = tmp;
}
-}
-
-void DRW_draw_pass(DRWPass *pass)
-{
- /* Start fresh */
- DST.shader = NULL;
- DST.tex_bind_id = 0;
- set_state(pass->state);
- BLI_listbase_clear(&DST.bound_texs);
+ /* issue query for the next frame */
+ glBeginQuery(GL_TIME_ELAPSED, pass->timer_queries[pass->back_idx]);
for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
draw_shgroup(shgroup);
@@ -1047,6 +1134,30 @@ void DRW_draw_pass(DRWPass *pass)
GPU_shader_unbind();
DST.shader = NULL;
}
+
+ glEndQuery(GL_TIME_ELAPSED);
+}
+
+void DRW_draw_callbacks_pre_scene(void)
+{
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+
+ ED_region_draw_cb_draw(DST.context, ar, REGION_DRAW_PRE_VIEW);
+}
+
+void DRW_draw_callbacks_post_scene(void)
+{
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+
+ ED_region_draw_cb_draw(DST.context, ar, REGION_DRAW_POST_VIEW);
}
/* Reset state to not interfer with other UI drawcall */
@@ -1056,102 +1167,81 @@ void DRW_state_reset(void)
state |= DRW_STATE_WRITE_DEPTH;
state |= DRW_STATE_WRITE_COLOR;
state |= DRW_STATE_DEPTH_LESS;
- set_state(state);
+ set_state(state, true);
}
-#endif
-/* ****************************************** Settings ******************************************/
-void *DRW_material_settings_get(Material *ma, const char *engine_name)
-{
- MaterialEngineSettings *ms = NULL;
-
- ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name));
-
-#ifdef WITH_CLAY_ENGINE
- /* If the settings does not exists yet, create it */
- if (ms == NULL) {
- ms = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
- BLI_strncpy(ms->name, engine_name, 32);
-
- /* TODO make render_settings_create a polymorphic function */
- if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
- ms->data = CLAY_material_settings_create();
- }
- else {
- /* No engine matched */
- BLI_assert(false);
- }
-
- BLI_addtail(&ma->engines_settings, ms);
- }
#else
- return NULL;
+void DRW_draw_pass(DRWPass *UNUSED(pass))
+{
+}
+
#endif
- return ms->data;
-}
+/* ****************************************** Settings ******************************************/
-/* If scene is NULL, use context scene */
-void *DRW_render_settings_get(Scene *scene, const char *engine_name)
+bool DRW_is_object_renderable(Object *ob)
{
- RenderEngineSettings *rs = NULL;
+ Scene *scene = CTX_data_scene(DST.context);
+ Object *obedit = scene->obedit;
- if (scene == NULL)
- scene = CTX_data_scene(DST.context);
+ if (ob->type == OB_MESH) {
+ if (ob == obedit) {
+ IDProperty *props = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, "");
+ bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(props, "show_occlude_wire");
- rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name));
+ if (do_occlude_wire)
+ return false;
+ }
+ }
-#ifdef WITH_CLAY_ENGINE
- /* If the settings does not exists yet, create it */
- if (rs == NULL) {
- rs = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+ return true;
+}
- BLI_strncpy(rs->name, engine_name, 32);
+/* ****************************************** Framebuffers ******************************************/
- /* TODO make render_settings_create a polymorphic function */
- if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
- rs->data = CLAY_render_settings_create();
- }
- else {
- /* No engine matched */
+static GPUTextureFormat convert_tex_format(int fbo_format, int *channels)
+{
+ switch (fbo_format) {
+ case DRW_BUF_RGBA_8: *channels = 4; return GPU_RGBA8;
+ case DRW_BUF_RGBA_16: *channels = 4; return GPU_RGBA16F;
+ case DRW_BUF_DEPTH_24: *channels = 1; return GPU_DEPTH_COMPONENT24;
+ default:
BLI_assert(false);
- }
-
- BLI_addtail(&scene->engines_settings, rs);
+ *channels = 4; return GPU_RGBA8;
}
-#else
- return NULL;
-#endif
-
- return rs->data;
}
-/* ****************************************** Framebuffers ******************************************/
+
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX],
int texnbr)
{
+ BLI_assert(texnbr <= MAX_FBO_TEX);
+
if (!*fb) {
int color_attachment = -1;
*fb = GPU_framebuffer_create();
- for (int i = 0; i < texnbr; ++i)
- {
+ for (int i = 0; i < texnbr; ++i) {
DRWFboTexture fbotex = textures[i];
-
+
if (!*fbotex.tex) {
+ int channels;
+ GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels);
+
/* TODO refine to opengl formats */
if (fbotex.format == DRW_BUF_DEPTH_16 ||
- fbotex.format == DRW_BUF_DEPTH_24) {
+ fbotex.format == DRW_BUF_DEPTH_24)
+ {
*fbotex.tex = GPU_texture_create_depth(width, height, NULL);
GPU_texture_compare_mode(*fbotex.tex, false);
GPU_texture_filter_mode(*fbotex.tex, false);
}
else {
- *fbotex.tex = GPU_texture_create_2D(width, height, NULL, NULL);
+ *fbotex.tex = GPU_texture_create_2D_custom(width, height, channels, gpu_format, NULL, NULL);
++color_attachment;
}
}
-
+
GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment);
}
@@ -1168,6 +1258,24 @@ void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
GPU_framebuffer_bind(fb);
}
+void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth)
+{
+ if (color) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]);
+ }
+ if (depth) {
+ glDepthMask(GL_TRUE);
+ glClearDepth(clear_depth);
+ }
+ if (stencil) {
+ glStencilMask(0xFF);
+ }
+ glClear(((color) ? GL_COLOR_BUFFER_BIT : 0) |
+ ((depth) ? GL_DEPTH_BUFFER_BIT : 0) |
+ ((stencil) ? GL_STENCIL_BUFFER_BIT : 0));
+}
+
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot)
{
GPU_framebuffer_texture_attach(fb, tex, slot);
@@ -1178,7 +1286,21 @@ void DRW_framebuffer_texture_detach(GPUTexture *tex)
GPU_framebuffer_texture_detach(tex);
}
+void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth)
+{
+ GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
+}
+
/* ****************************************** Viewport ******************************************/
+static void *DRW_viewport_engine_data_get(void *engine_type)
+{
+ void *data = GPU_viewport_engine_data_get(DST.viewport, engine_type);
+
+ if (data == NULL) {
+ data = GPU_viewport_engine_data_create(DST.viewport, engine_type);
+ }
+ return data;
+}
float *DRW_viewport_size_get(void)
{
@@ -1195,25 +1317,23 @@ float *DRW_viewport_pixelsize_get(void)
return &DST.pixsize;
}
-void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes, void **storage)
+/* It also stores viewport variable to an immutable place: DST
+ * This is because a cache uniform only store reference
+ * to its value. And we don't want to invalidate the cache
+ * if this value change per viewport */
+static void DRW_viewport_var_init(const bContext *C)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- GPUViewport *viewport = rv3d->viewport;
-
- GPU_viewport_get_engine_data(viewport, buffers, textures, passes, storage);
/* Refresh DST.size */
- DefaultTextureList *txl = (DefaultTextureList *)*textures;
- DST.size[0] = (float)GPU_texture_width(txl->color);
- DST.size[1] = (float)GPU_texture_height(txl->color);
+ int size[2];
+ GPU_viewport_size_get(DST.viewport, size);
+ DST.size[0] = size[0];
+ DST.size[1] = size[1];
- DefaultFramebufferList *fbl = (DefaultFramebufferList *)*buffers;
+ DefaultFramebufferList *fbl = (DefaultFramebufferList *)GPU_viewport_framebuffer_list_get(DST.viewport);
DST.default_framebuffer = fbl->default_fb;
- DST.current_txl = (TextureList *)*textures;
- DST.current_fbl = (FramebufferList *)*buffers;
- DST.current_psl = (PassList *)*passes;
-
/* Refresh DST.screenvecs */
copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
@@ -1233,8 +1353,10 @@ void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
if (type == DRW_MAT_PERS)
copy_m4_m4(mat, rv3d->persmat);
- else if (type == DRW_MAT_WIEW)
+ else if (type == DRW_MAT_VIEW)
copy_m4_m4(mat, rv3d->viewmat);
+ else if (type == DRW_MAT_VIEWINV)
+ copy_m4_m4(mat, rv3d->viewinv);
else if (type == DRW_MAT_WIN)
copy_m4_m4(mat, rv3d->winmat);
}
@@ -1245,28 +1367,491 @@ bool DRW_viewport_is_persp_get(void)
return rv3d->is_persp;
}
-bool DRW_viewport_cache_is_dirty(void)
+DefaultFramebufferList *DRW_viewport_framebuffer_list_get(void)
+{
+ return GPU_viewport_framebuffer_list_get(DST.viewport);
+}
+
+DefaultTextureList *DRW_viewport_texture_list_get(void)
+{
+ return GPU_viewport_texture_list_get(DST.viewport);
+}
+
+/* **************************************** OBJECTS *************************************** */
+
+typedef struct ObjectEngineData {
+ struct ObjectEngineData *next, *prev;
+ DrawEngineType *engine_type;
+ void *storage;
+} ObjectEngineData;
+
+void **DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type)
+{
+ ObjectEngineData *oed;
+
+ for (oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->engine_type == engine_type) {
+ return &oed->storage;
+ }
+ }
+
+ oed = MEM_callocN(sizeof(ObjectEngineData), "ObjectEngineData");
+ oed->engine_type = engine_type;
+ BLI_addtail(&ob->drawdata, oed);
+
+ return &oed->storage;
+}
+
+void DRW_object_engine_data_free(Object *ob)
+{
+ for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->storage) {
+ MEM_freeN(oed->storage);
+ }
+ }
+
+ BLI_freelistN(&ob->drawdata);
+}
+
+/* **************************************** RENDERING ************************************** */
+
+#define TIMER_FALLOFF 0.1f
+
+static void DRW_engines_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->engine_init) {
+ engine->engine_init(data);
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->init_time = data->init_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+}
+
+static void DRW_engines_cache_init(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+ data->cache_time = 0.0;
+
+ if (engine->cache_init) {
+ engine->cache_init(data);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_cache_populate(Object *ob)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->cache_populate) {
+ engine->cache_populate(data, ob);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_cache_finish(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->cache_finish) {
+ engine->cache_finish(data);
+ }
+
+ data->cache_time += (PIL_check_seconds_timer() - stime) * 1e3;
+ }
+}
+
+static void DRW_engines_draw_background(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->draw_background) {
+ engine->draw_background(data);
+ return;
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->background_time = data->background_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+
+ /* No draw_background found, doing default background */
+ DRW_draw_background();
+}
+
+static void DRW_engines_draw_scene(void)
+{
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ double stime = PIL_check_seconds_timer();
+
+ if (engine->draw_scene) {
+ engine->draw_scene(data);
+ }
+
+ double ftime = (PIL_check_seconds_timer() - stime) * 1e3;
+ data->render_time = data->render_time * (1.0f - TIMER_FALLOFF) + ftime * TIMER_FALLOFF; /* exp average */
+ }
+}
+
+static void use_drw_engine(DrawEngineType *engine)
+{
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "enabled engine link data");
+ ld->data = engine;
+ BLI_addtail(&DST.enabled_engines, ld);
+}
+
+/* TODO revisit this when proper layering is implemented */
+/* Gather all draw engines needed and store them in DST.enabled_engines
+ * That also define the rendering order of engines */
+static void DRW_engines_enable(const bContext *C)
+{
+ /* TODO layers */
+ Scene *scene = CTX_data_scene(C);
+ RenderEngineType *type = RE_engines_find(scene->r.engine);
+ use_drw_engine(type->draw_engine);
+
+ /* TODO Refine the folowing logic based on objects states
+ * not on global state.
+ * Order is important */
+ use_drw_engine(&draw_engine_object_type);
+
+ switch (CTX_data_mode_enum(C)) {
+ case CTX_MODE_EDIT_MESH:
+ use_drw_engine(&draw_engine_edit_mesh_type);
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ use_drw_engine(&draw_engine_edit_curve_type);
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ use_drw_engine(&draw_engine_edit_surface_type);
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ use_drw_engine(&draw_engine_edit_text_type);
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ use_drw_engine(&draw_engine_edit_armature_type);
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ use_drw_engine(&draw_engine_edit_metaball_type);
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ use_drw_engine(&draw_engine_edit_lattice_type);
+ break;
+ case CTX_MODE_POSE:
+ use_drw_engine(&draw_engine_pose_type);
+ break;
+ case CTX_MODE_SCULPT:
+ use_drw_engine(&draw_engine_sculpt_type);
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ use_drw_engine(&draw_engine_paint_weight_type);
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ use_drw_engine(&draw_engine_paint_vertex_type);
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ use_drw_engine(&draw_engine_paint_texture_type);
+ break;
+ case CTX_MODE_PARTICLE:
+ use_drw_engine(&draw_engine_particle_type);
+ break;
+ case CTX_MODE_OBJECT:
+ break;
+ }
+}
+
+static void DRW_engines_disable(void)
+{
+ BLI_freelistN(&DST.enabled_engines);
+}
+
+static unsigned int DRW_engines_get_hash(void)
+{
+ unsigned int hash = 0;
+ /* The cache depends on enabled engines */
+ /* FIXME : if collision occurs ... segfault */
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ DrawEngineType *engine = link->data;
+ hash += BLI_ghashutil_strhash_p(engine->idname);
+ }
+
+ return hash;
+}
+
+static void draw_stat(rcti *rect, int u, int v, const char *txt, const int size)
+{
+ BLF_draw_default_ascii(rect->xmin + (1 + u * 5) * U.widget_unit,
+ rect->ymax - (3 + v++) * U.widget_unit, 0.0f,
+ txt, size);
+}
+
+/* CPU stats */
+static void DRW_debug_cpu_stats(void)
+{
+ int u, v;
+ double cache_tot_time = 0.0, init_tot_time = 0.0, background_tot_time = 0.0, render_tot_time = 0.0, tot_time = 0.0;
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ /* row by row */
+ v = 0; u = 0;
+ /* Label row */
+ char col_label[32];
+ sprintf(col_label, "Engine");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Cache");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Init");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Background");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Render");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(col_label, "Total (w/o cache)");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ v++;
+
+ /* Engines rows */
+ char time_to_txt[16];
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ u = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+
+ draw_stat(&rect, u++, v, engine->idname, sizeof(engine->idname));
+
+ cache_tot_time += data->cache_time;
+ sprintf(time_to_txt, "%.2fms", data->cache_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ init_tot_time += data->init_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ background_tot_time += data->background_time;
+ sprintf(time_to_txt, "%.2fms", data->background_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ render_tot_time += data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+
+ tot_time += data->init_time + data->background_time + data->render_time;
+ sprintf(time_to_txt, "%.2fms", data->init_time + data->background_time + data->render_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
+
+ /* Totals row */
+ u = 0;
+ sprintf(col_label, "Sub Total");
+ draw_stat(&rect, u++, v, col_label, sizeof(col_label));
+ sprintf(time_to_txt, "%.2fms", cache_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", init_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", background_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", render_tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+ sprintf(time_to_txt, "%.2fms", tot_time);
+ draw_stat(&rect, u++, v, time_to_txt, sizeof(time_to_txt));
+}
+
+/* Display GPU time for each passes */
+static void DRW_debug_gpu_stats(void)
+{
+ /* local coordinate visible rect inside region, to accomodate overlapping ui */
+ rcti rect;
+ struct ARegion *ar = CTX_wm_region(DST.context);
+ ED_region_visible_rect(ar, &rect);
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+
+ char time_to_txt[16];
+ char pass_name[MAX_PASS_NAME + 8];
+ int v = BLI_listbase_count(&DST.enabled_engines) + 3;
+ GLuint64 tot_time = 0;
+
+ for (LinkData *link = DST.enabled_engines.first; link; link = link->next) {
+ GLuint64 engine_time = 0;
+ DrawEngineType *engine = link->data;
+ ViewportEngineData *data = DRW_viewport_engine_data_get(engine);
+ int vsta = v;
+
+ draw_stat(&rect, 0, v, engine->idname, sizeof(engine->idname));
+ v++;
+
+ for (int i = 0; i < MAX_PASSES; ++i) {
+ DRWPass *pass = data->psl->passes[i];
+ if (pass != NULL) {
+ GLuint64 time;
+ glGetQueryObjectui64v(pass->timer_queries[pass->front_idx], GL_QUERY_RESULT, &time);
+ tot_time += time;
+ engine_time += time;
+
+ sprintf(pass_name, " |--> %s", pass->name);
+ draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
+
+ if (pass->wasdrawn)
+ sprintf(time_to_txt, "%.2fms", time / 1000000.0);
+ else
+ sprintf(time_to_txt, "Not drawn");
+ draw_stat(&rect, 2, v++, time_to_txt, sizeof(time_to_txt));
+
+ pass->wasdrawn = false;
+ }
+ }
+ /* engine total time */
+ sprintf(time_to_txt, "%.2fms", engine_time / 1000000.0);
+ draw_stat(&rect, 2, vsta, time_to_txt, sizeof(time_to_txt));
+ v++;
+ }
+
+ sprintf(pass_name, "Total GPU time %.2fms (%.1f fps)", tot_time / 1000000.0, 1000000000.0 / tot_time);
+ draw_stat(&rect, 0, v, pass_name, sizeof(pass_name));
+}
+
+/* Everything starts here.
+ * This function takes care of calling all cache and rendering functions
+ * for each relevant engine / mode engine. */
+void DRW_draw_view(const bContext *C)
+{
+ bool cache_is_dirty;
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ DST.viewport = rv3d->viewport;
+ v3d->zbuf = true;
+
+ /* Get list of enabled engines */
+ DRW_engines_enable(C);
+
+ /* Setup viewport */
+ cache_is_dirty = GPU_viewport_cache_validate(DST.viewport, DRW_engines_get_hash());
+ DRW_viewport_var_init(C);
+
+ /* Update ubos */
+ DRW_globals_update();
+
+ /* Init engines */
+ DRW_engines_init();
+
+ /* TODO : tag to refresh by the deps graph */
+ /* ideally only refresh when objects are added/removed */
+ /* or render properties / materials change */
+ if (cache_is_dirty) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ DRW_engines_cache_init();
+ DEG_OBJECT_ITER(sl, ob);
+ {
+ DRW_engines_cache_populate(ob);
+ }
+ DEG_OBJECT_ITER_END
+ DRW_engines_cache_finish();
+ }
+
+ /* Start Drawing */
+ DRW_engines_draw_background();
+
+ DRW_draw_callbacks_pre_scene();
+ // DRW_draw_grid();
+ DRW_engines_draw_scene();
+ DRW_draw_callbacks_post_scene();
+
+ DRW_draw_region_info();
+
+ if (G.debug_value > 20) {
+ DRW_debug_cpu_stats();
+ DRW_debug_gpu_stats();
+ }
+
+ DRW_state_reset();
+ DRW_engines_disable();
+}
+
+/* ****************************************** OTHER ***************************************** */
+
+const bContext *DRW_get_context(void)
{
- /* TODO Use a dirty flag */
- return (DST.current_psl->passes[0] == NULL);
+ return DST.context;
}
-/* ****************************************** INIT ******************************************/
+/* ****************************************** INIT ***************************************** */
+
+void DRW_engine_register(DrawEngineType *draw_engine_type)
+{
+ BLI_addtail(&DRW_engines, draw_engine_type);
+}
-void DRW_engines_init(void)
+void DRW_engines_register(void)
{
#ifdef WITH_CLAY_ENGINE
RE_engines_register(NULL, &viewport_clay_type);
+ RE_engines_register(NULL, &viewport_eevee_type);
+
+ DRW_engine_register(&draw_engine_object_type);
+ DRW_engine_register(&draw_engine_edit_armature_type);
+ DRW_engine_register(&draw_engine_edit_curve_type);
+ DRW_engine_register(&draw_engine_edit_lattice_type);
+ DRW_engine_register(&draw_engine_edit_mesh_type);
+ DRW_engine_register(&draw_engine_edit_metaball_type);
+ DRW_engine_register(&draw_engine_edit_surface_type);
+ DRW_engine_register(&draw_engine_edit_text_type);
+ DRW_engine_register(&draw_engine_paint_texture_type);
+ DRW_engine_register(&draw_engine_paint_vertex_type);
+ DRW_engine_register(&draw_engine_paint_weight_type);
+ DRW_engine_register(&draw_engine_particle_type);
+ DRW_engine_register(&draw_engine_pose_type);
+ DRW_engine_register(&draw_engine_sculpt_type);
#endif
}
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
void DRW_engines_free(void)
{
#ifdef WITH_CLAY_ENGINE
- clay_engine_free();
-
DRW_shape_cache_free();
+ DrawEngineType *next;
+ for (DrawEngineType *type = DRW_engines.first; type; type = next) {
+ next = type->next;
+ BLI_remlink(&R_engines, type);
+
+ if (type->engine_free) {
+ type->engine_free();
+ }
+ }
+
+ if (globals_ubo)
+ GPU_uniformbuffer_free(globals_ubo);
+
BLI_remlink(&R_engines, &viewport_clay_type);
#endif
-} \ No newline at end of file
+}
diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c
deleted file mode 100644
index 0298db1a5ca..00000000000
--- a/source/blender/draw/intern/draw_mode_pass.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
- * Copyright 2016, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributor(s): Blender Institute
- *
- */
-
-/** \file blender/draw/draw_mode_pass.c
- * \ingroup draw
- */
-
-#include "DNA_userdef_types.h"
-
-#include "GPU_shader.h"
-
-#include "UI_resources.h"
-
-#include "BKE_global.h"
-
-#include "draw_mode_pass.h"
-
-/* ************************** OBJECT MODE ******************************* */
-
-/* Store list of shading group for easy access*/
-
-/* Empties */
-static DRWShadingGroup *plain_axes;
-static DRWShadingGroup *cube;
-static DRWShadingGroup *circle;
-static DRWShadingGroup *sphere;
-static DRWShadingGroup *cone;
-static DRWShadingGroup *single_arrow;
-static DRWShadingGroup *single_arrow_line;
-static DRWShadingGroup *arrows;
-
-/* Lamps */
-static DRWShadingGroup *lamp_center;
-static DRWShadingGroup *lamp_center_group;
-static DRWShadingGroup *lamp_groundpoint;
-static DRWShadingGroup *lamp_groundline;
-static DRWShadingGroup *lamp_circle;
-static DRWShadingGroup *lamp_circle_shadow;
-static DRWShadingGroup *lamp_sunrays;
-
-/* Helpers */
-static DRWShadingGroup *relationship_lines;
-
-/* Objects Centers */
-static DRWShadingGroup *center_active;
-static DRWShadingGroup *center_selected;
-static DRWShadingGroup *center_deselected;
-
-/* Colors & Constant */
-static float colorWire[4], colorWireEdit[4];
-static float colorActive[4], colorSelect[4], colorTransform[4], colorGroup[4], colorGroupActive[4];
-static float colorEmpty[4], colorLamp[4], colorCamera[4], colorSpeaker[4];
-static float lampCenterSize, lampCircleRad, lampCircleShadowRad, colorLampNoAlpha[4];
-
-static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
-{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
-
- DRWShadingGroup *grp = DRW_shgroup_line_batch_create(sh, pass);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
-
- return grp;
-}
-
-static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size)
-{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
-
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
- DRW_shgroup_uniform_float(grp, "size", size, 1);
- DRW_shgroup_state_set(grp, DRW_STATE_POINT);
-
- return grp;
-}
-
-static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4])
-{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
-
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
-
- return grp;
-}
-
-static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4])
-{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
-
- DRWShadingGroup *grp = DRW_shgroup_point_batch_create(sh, pass);
- DRW_shgroup_uniform_vec4(grp, "color", color, 1);
- DRW_shgroup_state_set(grp, DRW_STATE_POINT);
-
- return grp;
-}
-
-static DRWShadingGroup *shgroup_instance_screenspace(DRWPass *pass, struct Batch *geom, float *size)
-{
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR
-);
-
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
- DRW_shgroup_attrib_float(grp, "world_pos", 3);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_uniform_float(grp, "size", size, 1);
- DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
- DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
- DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
-
- return grp;
-}
-
-static DRWShadingGroup *shgroup_instance(DRWPass *pass, struct Batch *geom)
-{
- GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE);
-
- DRWShadingGroup *grp = DRW_shgroup_instance_create(sh_inst, pass, geom);
- DRW_shgroup_attrib_float(grp, "color", 3);
- DRW_shgroup_attrib_float(grp, "size", 1);
- DRW_shgroup_attrib_float(grp, "InstanceModelMatrix", 16);
-
- return grp;
-}
-
-/* This Function setup the passes needed for the mode rendering.
- * The passes are populated by the rendering engine using the DRW_shgroup_* functions. */
-void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPass **non_meshes, DRWPass **ob_center)
-{
- UI_GetThemeColor4fv(TH_WIRE, colorWire);
- UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit);
- UI_GetThemeColor4fv(TH_ACTIVE, colorActive);
- UI_GetThemeColor4fv(TH_SELECT, colorSelect);
- UI_GetThemeColor4fv(TH_TRANSFORM, colorTransform);
- UI_GetThemeColor4fv(TH_GROUP_ACTIVE, colorGroupActive);
- UI_GetThemeColor4fv(TH_GROUP, colorGroup);
- UI_GetThemeColor4fv(TH_LAMP, colorLamp);
- UI_GetThemeColor4fv(TH_LAMP, colorLampNoAlpha);
- UI_GetThemeColor4fv(TH_SPEAKER, colorSpeaker);
- UI_GetThemeColor4fv(TH_CAMERA, colorCamera);
- UI_GetThemeColor4fv(TH_EMPTY, colorEmpty);
-
- colorLampNoAlpha[3] = 1.0f;
-
- if (wire_overlay) {
- /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND;
- *wire_overlay = DRW_pass_create("Wire Overlays Pass", state);
- }
-
- if (wire_outline) {
- /* This pass can draw mesh outlines and/or fancy wireframe */
- /* Fancy wireframes are not meant to be occluded (without Z offset) */
- /* Outlines and Fancy Wires use the same VBO */
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
- *wire_outline = DRW_pass_create("Wire + Outlines Pass", state);
- }
-
- if (non_meshes) {
- /* Non Meshes Pass (Camera, empties, lamps ...) */
- DRWShadingGroup *grp;
- struct Batch *geom;
-
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
- state |= DRW_STATE_WIRE;
- *non_meshes = DRW_pass_create("Non Meshes Pass", state);
-
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
-
- /* Empties */
- geom = DRW_cache_plain_axes_get();
- plain_axes = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_cube_get();
- cube = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_circle_get();
- circle = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_empty_sphere_get();
- sphere = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_empty_cone_get();
- cone = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_single_arrow_get();
- single_arrow = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_single_line_get();
- single_arrow_line = shgroup_instance(*non_meshes, geom);
-
- geom = DRW_cache_single_arrow_get();
- arrows = shgroup_instance(*non_meshes, geom);
-
- /* Lamps */
- lampCenterSize = (U.obcenter_dia + 1.5f) * U.pixelsize;
- lampCircleRad = U.pixelsize * 9.0f;
- lampCircleShadowRad = lampCircleRad + U.pixelsize * 3.0f;
- /* TODO
- * for now we create 3 times the same VBO with only lamp center coordinates
- * but ideally we would only create it once */
- lamp_center = shgroup_dynpoints_uniform_color(*non_meshes, colorLampNoAlpha, &lampCenterSize);
- lamp_center_group = shgroup_dynpoints_uniform_color(*non_meshes, colorGroup, &lampCenterSize);
-
- geom = DRW_cache_lamp_get();
- lamp_circle = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad);
- lamp_circle_shadow = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleShadowRad);
-
- geom = DRW_cache_lamp_sunrays_get();
- lamp_sunrays = shgroup_instance_screenspace(*non_meshes, geom, &lampCircleRad);
-
- lamp_groundline = shgroup_groundlines_uniform_color(*non_meshes, colorLamp);
- lamp_groundpoint = shgroup_groundpoints_uniform_color(*non_meshes, colorLamp);
-
- /* Stipple Wires */
- grp = DRW_shgroup_create(sh, *non_meshes);
- DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2);
-
- grp = DRW_shgroup_create(sh, *non_meshes);
- DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
-
- grp = DRW_shgroup_create(sh, *non_meshes);
- DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_4);
-
- /* Relationship Lines */
- relationship_lines = shgroup_dynlines_uniform_color(*non_meshes, colorWire);
- DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3);
- }
-
- if (ob_center) {
- /* Object Center pass grouped by State */
- DRWShadingGroup *grp;
- static float colorDeselect[4], outlineColor[4];
- static float outlineWidth, size;
-
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
- *ob_center = DRW_pass_create("Obj Center Pass", state);
-
- outlineWidth = 1.0f * U.pixelsize;
- size = U.obcenter_dia * U.pixelsize + outlineWidth;
- //UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -80, colorActive);
- //UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -80, colorSelect);
- UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, colorDeselect);
- UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
-
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
-
- /* Active */
- grp = DRW_shgroup_point_batch_create(sh, *ob_center);
- DRW_shgroup_uniform_float(grp, "size", &size, 1);
- DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
- DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1);
- DRW_shgroup_uniform_vec4(grp, "outlineColor", outlineColor, 1);
- center_active = grp;
-
- /* Select */
- grp = DRW_shgroup_point_batch_create(sh, *ob_center);
- DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1);
- center_selected = grp;
-
- /* Deselect */
- grp = DRW_shgroup_point_batch_create(sh, *ob_center);
- DRW_shgroup_uniform_vec4(grp, "color", colorDeselect, 1);
- center_deselected = grp;
- }
-}
-
-/* ******************************************** WIRES *********************************************** */
-
-/* TODO FINISH */
-/* Get the wire color theme_id of an object based on it's state
- * **color is a way to get a pointer to the static color var associated */
-static int draw_object_wire_theme(Object *ob, float **color)
-{
- const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
- /* confusing logic here, there are 2 methods of setting the color
- * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
- *
- * note: no theme yet for 'colindex' */
- int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
-
- if (//(scene->obedit == NULL) &&
- ((G.moving & G_TRANSFORM_OBJ) != 0) &&
- ((ob->base_flag & BASE_SELECTED) != 0))
- {
- theme_id = TH_TRANSFORM;
- }
- else {
- /* Sets the 'theme_id' or fallback to wire */
- if ((ob->flag & OB_FROMGROUP) != 0) {
- if ((ob->base_flag & BASE_SELECTED) != 0) {
- /* uses darker active color for non-active + selected */
- theme_id = TH_GROUP_ACTIVE;
-
- // if (scene->basact != base) {
- // theme_shade = -16;
- // }
- }
- else {
- theme_id = TH_GROUP;
- }
- }
- else {
- if ((ob->base_flag & BASE_SELECTED) != 0) {
- theme_id = //scene->basact == base ? TH_ACTIVE :
- TH_SELECT;
- }
- else {
- if (ob->type == OB_LAMP) theme_id = TH_LAMP;
- else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
- else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
- else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
- /* fallback to TH_WIRE */
- }
- }
- }
-
- if (color != NULL) {
- switch (theme_id) {
- case TH_WIRE_EDIT: *color = colorTransform; break;
- case TH_ACTIVE: *color = colorActive; break;
- case TH_SELECT: *color = colorSelect; break;
- case TH_GROUP: *color = colorGroup; break;
- case TH_GROUP_ACTIVE: *color = colorGroupActive; break;
- case TH_TRANSFORM: *color = colorTransform; break;
- case OB_SPEAKER: *color = colorSpeaker; break;
- case OB_CAMERA: *color = colorCamera; break;
- case OB_EMPTY: *color = colorEmpty; break;
- case OB_LAMP: *color = colorLamp; break;
- default: *color = colorWire; break;
- }
- }
-
- return theme_id;
-}
-
-void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob)
-{
-#if 1
- struct Batch *geom = DRW_cache_wire_overlay_get(ob);
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY);
-
- DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
- DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
-
- DRW_shgroup_call_add(grp, geom, ob->obmat);
-#else
- static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- struct Batch *geom = DRW_cache_wire_overlay_get(ob);
- GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
-
- DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
- DRW_shgroup_uniform_vec4(grp, "color", col, 1);
-
- DRW_shgroup_call_add(grp, geom, ob->obmat);
-#endif
-}
-
-void DRW_shgroup_wire_outline(DRWPass *wire_outline, Object *ob,
- const bool do_front, const bool do_back, const bool do_outline)
-{
- GPUShader *sh;
- struct Batch *geom = DRW_cache_wire_outline_get(ob);
-
- /* Get color */
- /* TODO get the right color depending on ob state (Groups, overides etc..) */
- static float frontcol[4], backcol[4], color[4];
- UI_GetThemeColor4fv(TH_ACTIVE, color);
- copy_v4_v4(frontcol, color);
- copy_v4_v4(backcol, color);
- backcol[3] = 0.333f;
- frontcol[3] = 0.667f;
-
-#if 1 /* New wire */
-
- bool is_perps = DRW_viewport_is_persp_get();
- static bool bTrue = true;
- static bool bFalse = false;
-
- /* Note (TODO) : this requires cache to be discarded on ortho/perp switch
- * It may be preferable (or not depending on performance implication)
- * to introduce a shader uniform switch */
- if (is_perps) {
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP);
- }
- else {
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
- }
-
- if (do_front || do_back) {
- bool *bFront = (do_front) ? &bTrue : &bFalse;
- bool *bBack = (do_back) ? &bTrue : &bFalse;
-
- DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
- DRW_shgroup_state_set(grp, DRW_STATE_WIRE);
- DRW_shgroup_uniform_vec4(grp, "frontColor", frontcol, 1);
- DRW_shgroup_uniform_vec4(grp, "backColor", backcol, 1);
- DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1);
- DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1);
- DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1);
- DRW_shgroup_call_add(grp, geom, ob->obmat);
- }
-
- if (do_outline) {
- DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
- DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
- DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1);
- DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1);
- DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1);
- DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1);
-
- DRW_shgroup_call_add(grp, geom, ob->obmat);
- }
-
-#else /* Old (flat) wire */
-
- sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
- DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
- DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
-
- DRW_shgroup_call_add(grp, geom, ob->obmat);
-#endif
-
-}
-
-/* ***************************** NON MESHES ********************** */
-
-static void DRW_draw_lamp(Object *ob)
-{
- Lamp *la = ob->data;
- float *color;
- int theme_id = draw_object_wire_theme(ob, &color);
-
- /* Don't draw the center if it's selected or active */
- if (theme_id == TH_GROUP)
- DRW_shgroup_dynamic_call_add(lamp_center_group, ob->obmat[3]);
- else if (theme_id == TH_LAMP)
- DRW_shgroup_dynamic_call_add(lamp_center, ob->obmat[3]);
-
- /* First circle */
- DRW_shgroup_dynamic_call_add(lamp_circle, ob->obmat[3], color);
-
- /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
- if (la->type != LA_HEMI) {
- DRW_shgroup_dynamic_call_add(lamp_circle_shadow, ob->obmat[3], color);
- }
-
- /* Sunrays */
- if (la->type == LA_SUN) {
- DRW_shgroup_dynamic_call_add(lamp_sunrays, ob->obmat[3], color);
- }
-
- /* Line and point going to the ground */
- DRW_shgroup_dynamic_call_add(lamp_groundline, ob->obmat[3]);
- DRW_shgroup_dynamic_call_add(lamp_groundpoint, ob->obmat[3]);
-}
-
-static void DRW_draw_empty(Object *ob)
-{
- float *color;
- draw_object_wire_theme(ob, &color);
-
- switch (ob->empty_drawtype) {
- case OB_PLAINAXES:
- DRW_shgroup_dynamic_call_add(plain_axes, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_SINGLE_ARROW:
- DRW_shgroup_dynamic_call_add(single_arrow, color, &ob->empty_drawsize, ob->obmat);
- DRW_shgroup_dynamic_call_add(single_arrow_line, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_CUBE:
- DRW_shgroup_dynamic_call_add(cube, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_CIRCLE:
- DRW_shgroup_dynamic_call_add(circle, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_EMPTY_SPHERE:
- DRW_shgroup_dynamic_call_add(sphere, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_EMPTY_CONE:
- DRW_shgroup_dynamic_call_add(cone, color, &ob->empty_drawsize, ob->obmat);
- break;
- case OB_ARROWS:
- DRW_shgroup_dynamic_call_add(arrows, color, &ob->empty_drawsize, ob->obmat);
- /* TODO Missing axes names */
- break;
- }
-}
-
-void DRW_shgroup_non_meshes(DRWPass *UNUSED(non_meshes), Object *ob)
-{
- switch (ob->type) {
- case OB_LAMP:
- DRW_draw_lamp(ob);
- break;
- case OB_CAMERA:
- case OB_EMPTY:
- DRW_draw_empty(ob);
- default:
- break;
- }
-}
-
-void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), Object *ob)
-{
- if (ob->parent) {
- DRW_shgroup_dynamic_call_add(relationship_lines, ob->obmat[3]);
- DRW_shgroup_dynamic_call_add(relationship_lines, ob->parent->obmat[3]);
- }
-}
-
-/* ***************************** COMMON **************************** */
-
-void DRW_shgroup_object_center(DRWPass *UNUSED(ob_center), Object *ob)
-{
- if ((ob->base_flag & BASE_SELECTED) != 0) {
- DRW_shgroup_dynamic_call_add(center_selected, ob->obmat[3]);
- }
- else if (0) {
- DRW_shgroup_dynamic_call_add(center_deselected, ob->obmat[3]);
- }
-}
diff --git a/source/blender/draw/intern/draw_view.c b/source/blender/draw/intern/draw_view.c
new file mode 100644
index 00000000000..3837a9e8d54
--- /dev/null
+++ b/source/blender/draw/intern/draw_view.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/intern/draw_view.c
+ * \ingroup draw
+ *
+ * Contains dynamic drawing using immediate mode
+ */
+
+#include "DNA_brush_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_userdef_types.h"
+#include "DNA_view3d_types.h"
+
+#include "ED_screen.h"
+#include "ED_transform.h"
+#include "ED_view3d.h"
+
+#include "GPU_draw.h"
+#include "GPU_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+#include "BKE_object.h"
+#include "BKE_paint.h"
+#include "BKE_unit.h"
+
+#include "DRW_render.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h"
+
+#include "draw_view.h"
+
+/* ******************** region info ***************** */
+
+void DRW_draw_region_info(void)
+{
+ const bContext *C = DRW_get_context();
+ ARegion *ar = CTX_wm_region(C);
+
+ DRW_draw_cursor();
+ view3d_draw_region_info(C, ar);
+}
+
+/* ************************* Grid ************************** */
+
+static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
+{
+ /* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
+ * x0 is gridline 0, the axis in screen space
+ * Area covers [0 .. max) pixels */
+
+ int first = (int)ceil(-x0 / dx);
+ int last = (int)floor((max - x0) / dx);
+
+ if (first <= last) {
+ *r_first = first;
+ *r_count = last - first + 1;
+ }
+ else {
+ *r_first = 0;
+ *r_count = 0;
+ }
+}
+
+static int gridline_count(ARegion *ar, double x0, double y0, double dx)
+{
+ /* x0 & y0 establish the "phase" of the grid within this 2D region
+ * dx is the frequency, shared by x & y directions
+ * pass in dx of smallest (highest precision) grid we want to draw */
+
+ int first, x_ct, y_ct;
+
+ gridline_range(x0, dx, ar->winx, &first, &x_ct);
+ gridline_range(y0, dx, ar->winy, &first, &y_ct);
+
+ int total_ct = x_ct + y_ct;
+
+ return total_ct;
+}
+
+static bool drawgrid_draw(ARegion *ar, double x0, double y0, double dx, int skip_mod, unsigned pos, unsigned col, GLubyte col_value[3])
+{
+ /* skip every skip_mod lines relative to each axis; they will be overlaid by another drawgrid_draw
+ * always skip exact x0 & y0 axes; they will be drawn later in color
+ *
+ * set grid color once, just before the first line is drawn
+ * it's harmless to set same color for every line, or every vertex
+ * but if no lines are drawn, color must not be set! */
+
+ const float x_max = (float)ar->winx;
+ const float y_max = (float)ar->winy;
+
+ int first, ct;
+ int x_ct = 0, y_ct = 0; /* count of lines actually drawn */
+ int lines_skipped_for_next_unit = 0;
+
+ /* draw vertical lines */
+ gridline_range(x0, dx, x_max, &first, &ct);
+
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
+
+ if (x_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
+
+ float x = (float)(x0 + i * dx);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, y_max);
+ ++x_ct;
+ }
+
+ /* draw horizontal lines */
+ gridline_range(y0, dx, y_max, &first, &ct);
+
+ for (int i = first; i < first + ct; ++i) {
+ if (i == 0)
+ continue;
+ else if (skip_mod && (i % skip_mod) == 0) {
+ ++lines_skipped_for_next_unit;
+ continue;
+ }
+
+ if (x_ct + y_ct == 0)
+ immAttrib3ub(col, col_value[0], col_value[1], col_value[2]);
+
+ float y = (float)(y0 + i * dx);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, x_max, y);
+ ++y_ct;
+ }
+
+ return lines_skipped_for_next_unit > 0;
+}
+
+#define GRID_MIN_PX_D 6.0
+#define GRID_MIN_PX_F 6.0f
+
+static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ double fx = rv3d->persmat[3][0];
+ double fy = rv3d->persmat[3][1];
+ double fw = rv3d->persmat[3][3];
+
+ const double wx = 0.5 * ar->winx; /* use double precision to avoid rounding errors */
+ const double wy = 0.5 * ar->winy;
+
+ double x = wx * fx / fw;
+ double y = wy * fy / fw;
+
+ double vec4[4] = { v3d->grid, v3d->grid, 0.0, 1.0 };
+ mul_m4_v4d(rv3d->persmat, vec4);
+ fx = vec4[0];
+ fy = vec4[1];
+ fw = vec4[3];
+
+ double dx = fabs(x - wx * fx / fw);
+ if (dx == 0) dx = fabs(y - wy * fy / fw);
+
+ x += wx;
+ y += wy;
+
+ /* now x, y, and dx have their final values
+ * (x,y) is the world origin (0,0,0) mapped to Area-relative screen space
+ * dx is the distance in pixels between grid lines -- same for horiz or vert grid lines */
+
+ glLineWidth(1.0f);
+
+#if 0 /* TODO: write to UI/widget depth buffer, not scene depth */
+ glDepthMask(GL_FALSE); /* disable write in zbuffer */
+#endif
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+
+ unsigned char col[3], col2[3];
+ UI_GetThemeColor3ubv(TH_GRID, col);
+
+ if (unit->system) {
+ const void *usys;
+ int len;
+
+ bUnit_GetSystem(unit->system, B_UNIT_LENGTH, &usys, &len);
+
+ bool first = true;
+
+ if (usys) {
+ int i = len;
+ while (i--) {
+ double scalar = bUnit_GetScaler(usys, i);
+
+ double dx_scalar = dx * scalar / (double)unit->scale_length;
+ if (dx_scalar < (GRID_MIN_PX_D * 2.0)) {
+ /* very very small grid items are less useful when dealing with units */
+ continue;
+ }
+
+ if (first) {
+ first = false;
+
+ /* Store the smallest drawn grid size units name so users know how big each grid cell is */
+ *grid_unit = bUnit_GetNameDisplay(usys, i);
+ rv3d->gridview = (float)((scalar * (double)v3d->grid) / (double)unit->scale_length);
+
+ int gridline_ct = gridline_count(ar, x, y, dx_scalar);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
+
+ immBegin(GL_LINES, gridline_ct * 2);
+ }
+
+ float blend_fac = 1.0f - ((GRID_MIN_PX_F * 2.0f) / (float)dx_scalar);
+ /* tweak to have the fade a bit nicer */
+ blend_fac = (blend_fac * blend_fac) * 2.0f;
+ CLAMP(blend_fac, 0.3f, 1.0f);
+
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, blend_fac, col2);
+
+ const int skip_mod = (i == 0) ? 0 : (int)round(bUnit_GetScaler(usys, i - 1) / scalar);
+ if (!drawgrid_draw(ar, x, y, dx_scalar, skip_mod, pos, color, col2))
+ break;
+ }
+ }
+ }
+ else {
+ const double sublines = v3d->gridsubdiv;
+ const float sublines_fl = v3d->gridsubdiv;
+
+ int grids_to_draw = 2; /* first the faint fine grid, then the bold coarse grid */
+
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ if (dx < GRID_MIN_PX_D) {
+ rv3d->gridview *= sublines_fl;
+ dx *= sublines;
+ grids_to_draw = (dx < GRID_MIN_PX_D) ? 0 : 1;
+ }
+ }
+ }
+ else {
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ rv3d->gridview /= sublines_fl;
+ dx /= sublines;
+ if (dx > (GRID_MIN_PX_D * 10.0)) {
+ grids_to_draw = 1;
+ }
+ }
+ }
+ }
+
+ int gridline_ct = gridline_count(ar, x, y, dx);
+ if (gridline_ct == 0)
+ goto drawgrid_cleanup; /* nothing to draw */
+
+ immBegin(GL_LINES, gridline_ct * 2);
+
+ if (grids_to_draw == 2) {
+ UI_GetThemeColorBlend3ubv(TH_HIGH_GRAD, TH_GRID, dx / (GRID_MIN_PX_D * 6.0), col2);
+ if (drawgrid_draw(ar, x, y, dx, v3d->gridsubdiv, pos, color, col2))
+ drawgrid_draw(ar, x, y, dx * sublines, 0, pos, color, col);
+ }
+ else if (grids_to_draw == 1) {
+ drawgrid_draw(ar, x, y, dx, 0, pos, color, col);
+ }
+ }
+
+ /* draw visible axes */
+ /* horizontal line */
+ if (0 <= y && y < ar->winy) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT) ? 'Y' : 'X');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, 0.0f, y);
+ immVertex2f(pos, (float)ar->winx, y);
+ }
+
+ /* vertical line */
+ if (0 <= x && x < ar->winx) {
+ UI_make_axis_color(col, col2, ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM) ? 'Y' : 'Z');
+ immAttrib3ub(color, col2[0], col2[1], col2[2]);
+ immVertex2f(pos, x, 0.0f);
+ immVertex2f(pos, x, (float)ar->winy);
+ }
+
+ immEnd();
+
+drawgrid_cleanup:
+ immUnbindProgram();
+
+#if 0 /* depth write is left enabled above */
+ glDepthMask(GL_TRUE); /* enable write in zbuffer */
+#endif
+}
+
+#undef DEBUG_GRID
+#undef GRID_MIN_PX_D
+#undef GRID_MIN_PX_F
+
+static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit)
+{
+ /* draw only if there is something to draw */
+ if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
+ /* draw how many lines?
+ * trunc(v3d->gridlines / 2) * 4
+ * + 2 for xy axes (possibly with special colors)
+ * + 1 for z axis (the only line not in xy plane)
+ * even v3d->gridlines are honored, odd rounded down */
+ const int gridlines = v3d->gridlines / 2;
+ const float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ const float grid = gridlines * grid_scale;
+
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR) && gridlines >= 1;
+
+ bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
+ bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
+ bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
+
+ unsigned char col_grid[3], col_axis[3];
+
+ glLineWidth(1.0f);
+
+ UI_GetThemeColor3ubv(TH_GRID, col_grid);
+
+ if (show_floor) {
+ const unsigned vertex_ct = 2 * (gridlines * 4 + 2);
+ const int sublines = v3d->gridsubdiv;
+
+ unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ immBegin(GL_LINES, vertex_ct);
+
+ /* draw normal grid lines */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_light, 10);
+
+ for (int a = 1; a <= gridlines; a++) {
+ /* skip emphasised divider lines */
+ if (a % sublines != 0) {
+ const float line = a * grid_scale;
+
+ immAttrib3ubv(color, col_grid_light);
+
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
+
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
+
+ /* draw emphasised grid lines */
+ UI_GetThemeColor3ubv(TH_BACK, col_bg);
+ /* emphasise division lines lighter instead of darker, if background is darker than grid */
+ UI_GetColorPtrShade3ubv(col_grid, col_grid_emphasise,
+ (col_grid[0] + col_grid[1] + col_grid[2] + 30 >
+ col_bg[0] + col_bg[1] + col_bg[2]) ? 20 : -10);
+
+ if (sublines <= gridlines) {
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ for (int a = sublines; a <= gridlines; a += sublines) {
+ const float line = a * grid_scale;
+
+ immVertex2f(pos, -grid, -line);
+ immVertex2f(pos, +grid, -line);
+ immVertex2f(pos, -grid, +line);
+ immVertex2f(pos, +grid, +line);
+
+ immVertex2f(pos, -line, -grid);
+ immVertex2f(pos, -line, +grid);
+ immVertex2f(pos, +line, -grid);
+ immVertex2f(pos, +line, +grid);
+ }
+ }
+
+ /* draw X axis */
+ if (show_axis_x) {
+ show_axis_x = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ immVertex2f(pos, -grid, 0.0f);
+ immVertex2f(pos, +grid, 0.0f);
+
+ /* draw Y axis */
+ if (show_axis_y) {
+ show_axis_y = false; /* drawing now, won't need to draw later */
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ }
+ else
+ immAttrib3ubv(color, col_grid_emphasise);
+
+ immVertex2f(pos, 0.0f, -grid);
+ immVertex2f(pos, 0.0f, +grid);
+
+ immEnd();
+ immUnbindProgram();
+
+ /* done with XY plane */
+ }
+
+ if (show_axis_x || show_axis_y || show_axis_z) {
+ /* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBegin(GL_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
+
+ if (show_axis_x) {
+ UI_make_axis_color(col_grid, col_axis, 'X');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, -grid, 0.0f, 0.0f);
+ immVertex3f(pos, +grid, 0.0f, 0.0f);
+ }
+
+ if (show_axis_y) {
+ UI_make_axis_color(col_grid, col_axis, 'Y');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, -grid, 0.0f);
+ immVertex3f(pos, 0.0f, +grid, 0.0f);
+ }
+
+ if (show_axis_z) {
+ UI_make_axis_color(col_grid, col_axis, 'Z');
+ immAttrib3ubv(color, col_axis);
+ immVertex3f(pos, 0.0f, 0.0f, -grid);
+ immVertex3f(pos, 0.0f, 0.0f, +grid);
+ }
+
+ immEnd();
+ immUnbindProgram();
+ }
+ }
+}
+
+void DRW_draw_grid(void)
+{
+ /* TODO viewport
+ * Missing is the flags to check whether to draw it
+ * for now now we are using the flags in v3d itself.
+ *
+ * Also for now always assume depth is there, so we
+ * draw on top of it.
+ */
+ /**
+ * Calculate pixel-size factor once, is used for lamps and object centers.
+ * Used by #ED_view3d_pixel_size and typically not accessed directly.
+ *
+ * \note #BKE_camera_params_compute_viewplane' also calculates a pixel-size value,
+ * passed to #RE_SetPixelSize, in ortho mode this is compatible with this value,
+ * but in perspective mode its offset by the near-clip.
+ *
+ * 'RegionView3D.pixsize' is used for viewport drawing, not rendering.
+ */
+ const bContext *C = DRW_get_context();
+ Scene *scene = CTX_data_scene(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ ARegion *ar = CTX_wm_region(C);
+ RegionView3D *rv3d = ar->regiondata;
+
+ const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
+ const char *grid_unit = NULL;
+
+ /* ortho grid goes first, does not write to depth buffer and doesn't need depth test so it will override
+ * objects if done last
+ * needs to be done always, gridview is adjusted in drawgrid() now, but only for ortho views.
+ */
+ rv3d->gridview = ED_view3d_grid_scale(scene, v3d, &grid_unit);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LESS);
+
+ if (!draw_floor) {
+ /* Do not get in front of overlays */
+ glDepthMask(GL_FALSE);
+
+ ED_region_pixelspace(ar);
+ *(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
+ drawgrid(&scene->unit, ar, v3d, &grid_unit);
+
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+ }
+ else {
+ glDepthMask(GL_TRUE);
+ drawfloor(scene, v3d, &grid_unit);
+ }
+}
+
+/* ************************* Background ************************** */
+
+void DRW_draw_background(void)
+{
+ /* Just to make sure */
+ glDepthMask(GL_TRUE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glStencilMask(0xFF);
+
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ /* Gradient background Color */
+ gpuMatrixBegin3D(); /* TODO: finish 2D API */
+
+ glDisable(GL_DEPTH_TEST);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ unsigned char col_hi[3], col_lo[3];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
+ UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+
+ immBegin(GL_QUADS, 4);
+ immAttrib3ubv(color, col_lo);
+ immVertex2f(pos, -1.0f, -1.0f);
+ immVertex2f(pos, 1.0f, -1.0f);
+
+ immAttrib3ubv(color, col_hi);
+ immVertex2f(pos, 1.0f, 1.0f);
+ immVertex2f(pos, -1.0f, 1.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ gpuMatrixEnd();
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+ else {
+ /* Solid background Color */
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+}
+
+/* **************************** 3D Cursor ******************************** */
+
+static bool is_cursor_visible(Scene *scene, SceneLayer *sl)
+{
+ Object *ob = OBACT_NEW;
+
+ /* don't draw cursor in paint modes, but with a few exceptions */
+ if (ob && ob->mode & OB_MODE_ALL_PAINT) {
+ /* exception: object is in weight paint and has deforming armature in pose mode */
+ if (ob->mode & OB_MODE_WEIGHT_PAINT) {
+ if (BKE_object_pose_armature_get(ob) != NULL) {
+ return true;
+ }
+ }
+ /* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ const Paint *p = BKE_paint_get_active(scene, sl);
+
+ if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
+ if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
+ return true;
+ }
+ }
+ }
+
+ /* no exception met? then don't draw cursor! */
+ return false;
+ }
+
+ return true;
+}
+
+void DRW_draw_cursor(void)
+{
+ const bContext *C = DRW_get_context();
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask(GL_FALSE);
+ glDisable(GL_DEPTH_TEST);
+ glLineWidth(1.0f);
+
+ if (is_cursor_visible(scene, sl)) {
+ float *co = ED_view3d_cursor3d_get(scene, v3d);
+ unsigned char crosshair_color[3];
+
+ const float f5 = 0.25f;
+ const float f10 = 0.5f;
+ const float f20 = 1.0f;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ unsigned int wpos = add_attrib(format, "world_pos", COMP_F32, 3, KEEP_FLOAT);
+
+ /* XXX Using instance shader without instance */
+ immBindBuiltinProgram(GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR);
+ immUniform1f("size", U.widget_unit);
+ immUniform1f("pixel_size", *DRW_viewport_pixelsize_get());
+ immUniformArray3fv("screen_vecs", DRW_viewport_screenvecs_get(), 2);
+ immUniformMatrix4fv("ViewProjectionMatrix", rv3d->persmat);
+
+ const int segments = 16;
+
+ immBegin(GL_LINE_LOOP, segments);
+ immAttrib3fv(wpos, co);
+
+ for (int i = 0; i < segments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)segments);
+ float x = f10 * cosf(angle);
+ float y = f10 * sinf(angle);
+
+ if (i % 2 == 0)
+ immAttrib3ub(color, 255, 0, 0);
+ else
+ immAttrib3ub(color, 255, 255, 255);
+
+ immVertex2f(pos, x, y);
+ }
+ immEnd();
+
+ UI_GetThemeColor3ubv(TH_VIEW_OVERLAY, crosshair_color);
+
+ immBegin(GL_LINES, 8);
+ immAttrib3ubv(color, crosshair_color);
+ immAttrib3fv(wpos, co);
+
+ immVertex2f(pos, -f20, 0);
+ immVertex2f(pos, -f5, 0);
+ immVertex2f(pos, +f5, 0);
+ immVertex2f(pos, +f20, 0);
+ immVertex2f(pos, 0, -f20);
+ immVertex2f(pos, 0, -f5);
+ immVertex2f(pos, 0, +f5);
+ immVertex2f(pos, 0, +f20);
+ immEnd();
+
+ immUnbindProgram();
+ }
+}
+
+/* **************************** 3D Manipulator ******************************** */
+
+void DRW_draw_manipulator(void)
+{
+ const bContext *C = DRW_get_context();
+ ARegion *region = CTX_wm_region(C);
+ View3D *v3d = CTX_wm_view3d(C);
+ v3d->zbuf = false;
+ WM_manipulatormap_draw(region->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D);
+}
diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_view.h
index d11213ec8a2..b400ceeffa2 100644
--- a/source/blender/draw/intern/draw_mode_pass.h
+++ b/source/blender/draw/intern/draw_view.h
@@ -19,27 +19,17 @@
*
*/
-/** \file draw_mode_pass.h
+/** \file draw_view.h
* \ingroup draw
*/
-#ifndef __DRAW_MODE_PASS_H__
-#define __DRAW_MODE_PASS_H__
+#ifndef __DRAW_VIEW_H__
+#define __DRAW_VIEW_H__
-#include "DRW_render.h"
+void DRW_draw_grid(void);
+void DRW_draw_region_info(void);
+void DRW_draw_background(void);
+void DRW_draw_cursor(void);
+void DRW_draw_manipulator(void);
-struct DRWPass;
-struct Batch;
-struct Object;
-
-void DRW_pass_setup_common(struct DRWPass **wire_overlay, struct DRWPass **wire_outline, struct DRWPass **non_meshes, struct DRWPass **ob_center);
-
-void DRW_shgroup_wire_overlay(struct DRWPass *wire_overlay, struct Object *ob);
-void DRW_shgroup_wire_outline(
- struct DRWPass *wire_outline, struct Object *ob, const bool do_front, const bool do_back, const bool do_outline);
-
-void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, struct Object *ob);
-void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, struct Object *ob);
-void DRW_shgroup_object_center(struct DRWPass *ob_center, struct Object *ob);
-
-#endif /* __DRAW_MODE_PASS_H__ */ \ No newline at end of file
+#endif /* __DRAW_VIEW_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h
new file mode 100644
index 00000000000..c3b4d5ee61a
--- /dev/null
+++ b/source/blender/draw/modes/draw_mode_engines.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/draw_mode_engines.h
+ * \ingroup draw
+ */
+
+#ifndef __DRAW_MODES_ENGINES_H__
+#define __DRAW_MODES_ENGINES_H__
+
+extern DrawEngineType draw_engine_object_type;
+extern DrawEngineType draw_engine_edit_armature_type;
+extern DrawEngineType draw_engine_edit_curve_type;
+extern DrawEngineType draw_engine_edit_lattice_type;
+extern DrawEngineType draw_engine_edit_mesh_type;
+extern DrawEngineType draw_engine_edit_metaball_type;
+extern DrawEngineType draw_engine_edit_surface_type;
+extern DrawEngineType draw_engine_edit_text_type;
+extern DrawEngineType draw_engine_paint_texture_type;
+extern DrawEngineType draw_engine_paint_vertex_type;
+extern DrawEngineType draw_engine_paint_weight_type;
+extern DrawEngineType draw_engine_particle_type;
+extern DrawEngineType draw_engine_pose_type;
+extern DrawEngineType draw_engine_sculpt_type;
+
+#endif /* __DRAW_MODES_ENGINES_H__ */ \ No newline at end of file
diff --git a/source/blender/draw/modes/edit_armature_mode.c b/source/blender/draw/modes/edit_armature_mode.c
new file mode 100644
index 00000000000..6111b9b160b
--- /dev/null
+++ b/source/blender/draw/modes/edit_armature_mode.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_armature_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_armature_types.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+extern GlobalsUboStorage ts;
+
+/* *********** LISTS *********** */
+/* keep it under MAX_PASSES */
+typedef struct EDIT_ARMATURE_PassList {
+ struct DRWPass *bone_solid;
+ struct DRWPass *bone_wire;
+ struct DRWPass *relationship;
+} EDIT_ARMATURE_PassList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_ARMATURE_StorageList {
+ struct g_data *g_data;
+} EDIT_ARMATURE_StorageList;
+
+typedef struct EDIT_ARMATURE_Data {
+ void *engine_type;
+ void *fbl;
+ void *txl;
+ EDIT_ARMATURE_PassList *psl;
+ void *stl;
+} EDIT_ARMATURE_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct g_data {
+ DRWShadingGroup *relationship_lines;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+static void EDIT_ARMATURE_cache_init(void *vedata)
+{
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Solid bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
+ }
+
+ {
+ /* Wire bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_wire = DRW_pass_create("Bone Wire Pass", state);
+ }
+
+ {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->relationship = DRW_pass_create("Bone Relationship Pass", state);
+
+ /* Relationship Lines */
+ stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->relationship, ts.colorWire);
+ DRW_shgroup_state_set(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ }
+}
+
+static void EDIT_ARMATURE_cache_populate(void *vedata, Object *ob)
+{
+ bArmature *arm = ob->data;
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+ EDIT_ARMATURE_StorageList *stl = ((EDIT_ARMATURE_Data *)vedata)->stl;
+
+ if (ob->type == OB_ARMATURE) {
+ if (arm->edbo) {
+ DRW_shgroup_armature_edit(ob, psl->bone_solid, psl->bone_wire, stl->g_data->relationship_lines);
+ }
+ }
+}
+
+static void EDIT_ARMATURE_draw_scene(void *vedata)
+{
+ EDIT_ARMATURE_PassList *psl = ((EDIT_ARMATURE_Data *)vedata)->psl;
+
+ DRW_draw_pass(psl->bone_solid);
+ DRW_draw_pass(psl->bone_wire);
+ DRW_draw_pass(psl->relationship);
+}
+
+#if 0
+void EDIT_ARMATURE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ //BKE_collection_engine_property_add_int(ces, "show_occlude_wire", false);
+}
+#endif
+
+DrawEngineType draw_engine_edit_armature_type = {
+ NULL, NULL,
+ N_("EditArmatureMode"),
+ NULL,
+ NULL,
+ &EDIT_ARMATURE_cache_init,
+ &EDIT_ARMATURE_cache_populate,
+ NULL,
+ NULL,
+ &EDIT_ARMATURE_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_curve_mode.c b/source/blender/draw/modes/edit_curve_mode.c
new file mode 100644
index 00000000000..d70db64d946
--- /dev/null
+++ b/source/blender/draw/modes/edit_curve_mode.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_curve_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_CURVE_engine_init() to
+ * initialize most of them and EDIT_CURVE_cache_init()
+ * for EDIT_CURVE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct EDIT_CURVE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_CURVE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_CURVE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_CURVE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_CURVE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_CURVE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_CURVE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_CURVE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} EDIT_CURVE_StorageList;
+
+typedef struct EDIT_CURVE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_CURVE_FramebufferList *fbl;
+ EDIT_CURVE_TextureList *txl;
+ EDIT_CURVE_PassList *psl;
+ EDIT_CURVE_StorageList *stl;
+} EDIT_CURVE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_CURVE_engine_init();
+ * free in EDIT_CURVE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+
+
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_CURVE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_CURVE_engine_init(void *vedata)
+{
+ EDIT_CURVE_TextureList *txl = ((EDIT_CURVE_Data *)vedata)->txl;
+ EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_CURVE_cache_init(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_CURVE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_CURVE_cache_finish(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_StorageList *stl = ((EDIT_CURVE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_CURVE_draw_scene(void *vedata)
+{
+ EDIT_CURVE_PassList *psl = ((EDIT_CURVE_Data *)vedata)->psl;
+ EDIT_CURVE_FramebufferList *fbl = ((EDIT_CURVE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_CURVE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_CURVE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_edit_curve_type = {
+ NULL, NULL,
+ N_("EditCurveMode"),
+ &EDIT_CURVE_engine_init,
+ &EDIT_CURVE_engine_free,
+ &EDIT_CURVE_cache_init,
+ &EDIT_CURVE_cache_populate,
+ &EDIT_CURVE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_CURVE_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_lattice_mode.c b/source/blender/draw/modes/edit_lattice_mode.c
new file mode 100644
index 00000000000..79d43c73378
--- /dev/null
+++ b/source/blender/draw/modes/edit_lattice_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_lattice_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_LATTICE_engine_init() to
+ * initialize most of them and EDIT_LATTICE_cache_init()
+ * for EDIT_LATTICE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct EDIT_LATTICE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_LATTICE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_LATTICE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_LATTICE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_LATTICE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_LATTICE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_LATTICE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_LATTICE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} EDIT_LATTICE_StorageList;
+
+typedef struct EDIT_LATTICE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_LATTICE_FramebufferList *fbl;
+ EDIT_LATTICE_TextureList *txl;
+ EDIT_LATTICE_PassList *psl;
+ EDIT_LATTICE_StorageList *stl;
+} EDIT_LATTICE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_LATTICE_engine_init();
+ * free in EDIT_LATTICE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_LATTICE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_LATTICE_engine_init(void *vedata)
+{
+ EDIT_LATTICE_TextureList *txl = ((EDIT_LATTICE_Data *)vedata)->txl;
+ EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_LATTICE_cache_init(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {1.0f, 0.0f, 0.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_LATTICE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_LATTICE_cache_finish(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_StorageList *stl = ((EDIT_LATTICE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_LATTICE_draw_scene(void *vedata)
+{
+ EDIT_LATTICE_PassList *psl = ((EDIT_LATTICE_Data *)vedata)->psl;
+ EDIT_LATTICE_FramebufferList *fbl = ((EDIT_LATTICE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_LATTICE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_LATTICE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_edit_lattice_type = {
+ NULL, NULL,
+ N_("EditLatticeMode"),
+ &EDIT_LATTICE_engine_init,
+ &EDIT_LATTICE_engine_free,
+ &EDIT_LATTICE_cache_init,
+ &EDIT_LATTICE_cache_populate,
+ &EDIT_LATTICE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_LATTICE_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_mesh_mode.c b/source/blender/draw/modes/edit_mesh_mode.c
new file mode 100644
index 00000000000..2991d212efa
--- /dev/null
+++ b/source/blender/draw/modes/edit_mesh_mode.c
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_mesh_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "GPU_shader.h"
+#include "DNA_view3d_types.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+extern char datatoc_edit_overlay_frag_glsl[];
+extern char datatoc_edit_overlay_vert_glsl[];
+extern char datatoc_edit_overlay_geom_tri_glsl[];
+extern char datatoc_edit_overlay_geom_edge_glsl[];
+extern char datatoc_edit_overlay_loosevert_vert_glsl[];
+extern char datatoc_edit_overlay_facedot_frag_glsl[];
+extern char datatoc_edit_overlay_facedot_vert_glsl[];
+extern char datatoc_edit_overlay_mix_vert_glsl[];
+extern char datatoc_edit_overlay_mix_frag_glsl[];
+extern char datatoc_edit_overlay_facefill_vert_glsl[];
+extern char datatoc_edit_overlay_facefill_frag_glsl[];
+extern char datatoc_edit_normals_vert_glsl[];
+extern char datatoc_edit_normals_geom_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
+
+/* *********** LISTS *********** */
+/* keep it under MAX_PASSES */
+typedef struct EDIT_MESH_PassList {
+ struct DRWPass *depth_hidden_wire;
+ struct DRWPass *edit_face_overlay;
+ struct DRWPass *edit_face_occluded;
+ struct DRWPass *mix_occlude;
+ struct DRWPass *facefill_occlude;
+ struct DRWPass *normals;
+} EDIT_MESH_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_MESH_FramebufferList {
+ struct GPUFrameBuffer *occlude_wire_fb;
+} EDIT_MESH_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_MESH_TextureList {
+ struct GPUTexture *occlude_wire_depth_tx;
+ struct GPUTexture *occlude_wire_color_tx;
+} EDIT_MESH_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_MESH_StorageList {
+ struct g_data *g_data;
+} EDIT_MESH_StorageList;
+
+typedef struct EDIT_MESH_Data {
+ void *engine_type;
+ EDIT_MESH_FramebufferList *fbl;
+ EDIT_MESH_TextureList *txl;
+ EDIT_MESH_PassList *psl;
+ void *stl;
+} EDIT_MESH_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ struct GPUShader *overlay_tri_sh;
+ struct GPUShader *overlay_tri_fast_sh;
+ struct GPUShader *overlay_tri_vcol_sh;
+ struct GPUShader *overlay_tri_vcol_fast_sh;
+ struct GPUShader *overlay_edge_sh;
+ struct GPUShader *overlay_edge_vcol_sh;
+ struct GPUShader *overlay_vert_sh;
+ struct GPUShader *overlay_facedot_sh;
+ struct GPUShader *overlay_mix_sh;
+ struct GPUShader *overlay_facefill_sh;
+ struct GPUShader *normals_face_sh;
+ struct GPUShader *normals_sh;
+ struct GPUShader *depth_sh;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ DRWShadingGroup *depth_shgrp_hidden_wire;
+
+ DRWShadingGroup *fnormals_shgrp;
+ DRWShadingGroup *vnormals_shgrp;
+ DRWShadingGroup *lnormals_shgrp;
+
+ DRWShadingGroup *face_overlay_shgrp;
+ DRWShadingGroup *ledges_overlay_shgrp;
+ DRWShadingGroup *lverts_overlay_shgrp;
+ DRWShadingGroup *facedot_overlay_shgrp;
+
+ DRWShadingGroup *face_occluded_shgrp;
+ DRWShadingGroup *ledges_occluded_shgrp;
+ DRWShadingGroup *lverts_occluded_shgrp;
+ DRWShadingGroup *facedot_occluded_shgrp;
+ DRWShadingGroup *facefill_occluded_shgrp;
+
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+static void EDIT_MESH_engine_init(void *vedata)
+{
+ EDIT_MESH_TextureList *txl = ((EDIT_MESH_Data *)vedata)->txl;
+ EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
+
+ float *viewport_size = DRW_viewport_size_get();
+
+ DRWFboTexture tex[2] = {{&txl->occlude_wire_depth_tx, DRW_BUF_DEPTH_24},
+ {&txl->occlude_wire_color_tx, DRW_BUF_RGBA_8}};
+ DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ (int)viewport_size[0], (int)viewport_size[1],
+ tex, 2);
+
+ if (!e_data.overlay_tri_sh) {
+ e_data.overlay_tri_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_tri_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define EDGE_FIX\n");
+ }
+ if (!e_data.overlay_tri_fast_sh) {
+ e_data.overlay_tri_fast_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_tri_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+ if (!e_data.overlay_tri_vcol_sh) {
+ e_data.overlay_tri_vcol_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_tri_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define EDGE_FIX\n"
+ "#define VERTEX_SELECTION\n");
+ }
+ if (!e_data.overlay_tri_vcol_fast_sh) {
+ e_data.overlay_tri_vcol_fast_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_tri_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define VERTEX_SELECTION\n");
+ }
+ if (!e_data.overlay_edge_sh) {
+ e_data.overlay_edge_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_edge_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+ if (!e_data.overlay_edge_vcol_sh) {
+ e_data.overlay_edge_vcol_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_vert_glsl,
+ datatoc_edit_overlay_geom_edge_glsl,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define VERTEX_SELECTION\n");
+ }
+ if (!e_data.overlay_vert_sh) {
+ e_data.overlay_vert_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_loosevert_vert_glsl, NULL,
+ datatoc_edit_overlay_frag_glsl,
+ datatoc_common_globals_lib_glsl, "#define VERTEX_SELECTION\n");
+ }
+ if (!e_data.overlay_facedot_sh) {
+ e_data.overlay_facedot_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_facedot_vert_glsl, NULL,
+ datatoc_edit_overlay_facedot_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+ if (!e_data.overlay_mix_sh) {
+ e_data.overlay_mix_sh = DRW_shader_create_fullscreen(datatoc_edit_overlay_mix_frag_glsl, NULL);
+ }
+ if (!e_data.overlay_facefill_sh) {
+ e_data.overlay_facefill_sh = DRW_shader_create_with_lib(datatoc_edit_overlay_facefill_vert_glsl, NULL,
+ datatoc_edit_overlay_facefill_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+ if (!e_data.normals_face_sh) {
+ e_data.normals_face_sh = DRW_shader_create(datatoc_edit_normals_vert_glsl,
+ datatoc_edit_normals_geom_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl, "#define FACE_NORMALS\n");
+ }
+ if (!e_data.normals_sh) {
+ e_data.normals_sh = DRW_shader_create(datatoc_edit_normals_vert_glsl,
+ datatoc_edit_normals_geom_glsl,
+ datatoc_gpu_shader_uniform_color_frag_glsl, NULL);
+ }
+ if (!e_data.depth_sh) {
+ e_data.depth_sh = DRW_shader_create_3D_depth_only();
+ }
+}
+
+static DRWPass *edit_mesh_create_overlay_pass(DRWShadingGroup **face_shgrp, DRWShadingGroup **ledges_shgrp,
+ DRWShadingGroup **lverts_shgrp, DRWShadingGroup **facedot_shgrp,
+ float *faceAlpha, DRWState statemod)
+{
+ static struct GPUShader *tri_sh, *ledge_sh;
+ const struct bContext *C = DRW_get_context();
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ ToolSettings *tsettings = scene->toolsettings;
+
+ if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0) {
+ ledge_sh = e_data.overlay_edge_vcol_sh;
+
+ if ((rv3d->rflag & RV3D_NAVIGATING) != 0)
+ tri_sh = e_data.overlay_tri_vcol_fast_sh;
+ else
+ tri_sh = e_data.overlay_tri_vcol_sh;
+ }
+ else {
+ ledge_sh = e_data.overlay_edge_sh;
+
+ if ((rv3d->rflag & RV3D_NAVIGATING) != 0)
+ tri_sh = e_data.overlay_tri_fast_sh;
+ else
+ tri_sh = e_data.overlay_tri_sh;
+ }
+
+ DRWPass *pass = DRW_pass_create("Edit Mesh Face Overlay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_POINT | statemod);
+
+ *face_shgrp = DRW_shgroup_create(tri_sh, pass);
+ DRW_shgroup_uniform_block(*face_shgrp, "globalsBlock", globals_ubo, 0);
+ DRW_shgroup_uniform_vec2(*face_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+ DRW_shgroup_uniform_float(*face_shgrp, "faceAlphaMod", faceAlpha, 1);
+
+ *ledges_shgrp = DRW_shgroup_create(ledge_sh, pass);
+ DRW_shgroup_uniform_vec2(*ledges_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+
+ if ((tsettings->selectmode & (SCE_SELECT_VERTEX)) != 0) {
+ *lverts_shgrp = DRW_shgroup_create(e_data.overlay_vert_sh, pass);
+ DRW_shgroup_uniform_vec2(*lverts_shgrp, "viewportSize", DRW_viewport_size_get(), 1);
+ }
+
+ if ((tsettings->selectmode & (SCE_SELECT_FACE)) != 0) {
+ *facedot_shgrp = DRW_shgroup_create(e_data.overlay_facedot_sh, pass);
+ }
+
+ return pass;
+}
+
+static float backwire_opacity;
+static float face_mod;
+static float size_normal;
+
+static void EDIT_MESH_cache_init(void *vedata)
+{
+ EDIT_MESH_TextureList *txl = ((EDIT_MESH_Data *)vedata)->txl;
+ EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
+ EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ const struct bContext *C = DRW_get_context();
+ View3D *v3d = CTX_wm_view3d(C);
+
+ bool do_zbufclip = ((v3d->flag & V3D_ZBUF_SELECT) == 0);
+
+ static float zero = 0.0f;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Complementary Depth Pass */
+ psl->depth_hidden_wire = DRW_pass_create("Depth Pass Hidden Wire", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_CULL_BACK);
+ stl->g_data->depth_shgrp_hidden_wire = DRW_shgroup_create(e_data.depth_sh, psl->depth_hidden_wire);
+ }
+
+ {
+ /* Normals */
+ psl->normals = DRW_pass_create("Edit Mesh Normals Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS);
+
+ stl->g_data->fnormals_shgrp = DRW_shgroup_create(e_data.normals_face_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->fnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->fnormals_shgrp, "color", ts.colorNormal, 1);
+
+ stl->g_data->vnormals_shgrp = DRW_shgroup_create(e_data.normals_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1);
+
+ stl->g_data->lnormals_shgrp = DRW_shgroup_create(e_data.normals_sh, psl->normals);
+ DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
+ DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1);
+ }
+
+ if (!do_zbufclip) {
+ psl->edit_face_overlay = edit_mesh_create_overlay_pass(&stl->g_data->face_overlay_shgrp, &stl->g_data->ledges_overlay_shgrp, &stl->g_data->lverts_overlay_shgrp,
+ &stl->g_data->facedot_overlay_shgrp, &face_mod, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND);
+ }
+ else {
+ /* We render all wires with depth and opaque to a new fbo and blend the result based on depth values */
+ psl->edit_face_occluded = edit_mesh_create_overlay_pass(&stl->g_data->face_occluded_shgrp, &stl->g_data->ledges_occluded_shgrp, &stl->g_data->lverts_occluded_shgrp,
+ &stl->g_data->facedot_occluded_shgrp, &zero, DRW_STATE_DEPTH_LESS | DRW_STATE_WRITE_DEPTH);
+
+ /* however we loose the front faces value (because we need the depth of occluded wires and
+ * faces are alpha blended ) so we recover them in a new pass. */
+ psl->facefill_occlude = DRW_pass_create("Front Face Color", DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND);
+ stl->g_data->facefill_occluded_shgrp = DRW_shgroup_create(e_data.overlay_facefill_sh, psl->facefill_occlude);
+ DRW_shgroup_uniform_block(stl->g_data->facefill_occluded_shgrp, "globalsBlock", globals_ubo, 0);
+
+ /* we need a full screen pass to combine the result */
+ struct Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ psl->mix_occlude = DRW_pass_create("Mix Occluded Wires", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
+ DRWShadingGroup *mix_shgrp = DRW_shgroup_create(e_data.overlay_mix_sh, psl->mix_occlude);
+ DRW_shgroup_call_add(mix_shgrp, quad, NULL);
+ DRW_shgroup_uniform_float(mix_shgrp, "alpha", &backwire_opacity, 1);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "wireColor", &txl->occlude_wire_color_tx, 0);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "wireDepth", &txl->occlude_wire_depth_tx, 2);
+ DRW_shgroup_uniform_buffer(mix_shgrp, "sceneDepth", &dtxl->depth, 3);
+ }
+}
+
+static void edit_mesh_add_ob_to_pass(Scene *scene, Object *ob, DRWShadingGroup *face_shgrp, DRWShadingGroup *ledges_shgrp,
+ DRWShadingGroup *lverts_shgrp, DRWShadingGroup *facedot_shgrp, DRWShadingGroup *facefill_shgrp)
+{
+ struct Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts, *geo_ovl_fcenter;
+ ToolSettings *tsettings = scene->toolsettings;
+
+ DRW_cache_wire_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
+ DRW_shgroup_call_add(face_shgrp, geo_ovl_tris, ob->obmat);
+ DRW_shgroup_call_add(ledges_shgrp, geo_ovl_ledges, ob->obmat);
+
+ if (facefill_shgrp)
+ DRW_shgroup_call_add(facefill_shgrp, geo_ovl_tris, ob->obmat);
+
+ if ((tsettings->selectmode & SCE_SELECT_VERTEX) != 0)
+ DRW_shgroup_call_add(lverts_shgrp, geo_ovl_lverts, ob->obmat);
+
+ if ((tsettings->selectmode & SCE_SELECT_FACE) != 0) {
+ geo_ovl_fcenter = DRW_cache_face_centers_get(ob);
+ DRW_shgroup_call_add(facedot_shgrp, geo_ovl_fcenter, ob->obmat);
+ }
+}
+
+static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_MESH_StorageList *stl = ((EDIT_MESH_Data *)vedata)->stl;
+ const struct bContext *C = DRW_get_context();
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obedit = scene->obedit;
+ struct Batch *geom;
+
+ if (ob->type == OB_MESH) {
+ if (ob == obedit) {
+ IDProperty *ces_mode_ed = BKE_object_collection_engine_get(ob, COLLECTION_MODE_EDIT, "");
+ bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire");
+ backwire_opacity = BKE_collection_engine_property_value_get_float(ces_mode_ed, "backwire_opacity"); /* Updating uniform */
+
+ bool fnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "face_normals_show");
+ bool vnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "vert_normals_show");
+ bool lnormals_do = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "loop_normals_show");
+ size_normal = BKE_collection_engine_property_value_get_float(ces_mode_ed, "normals_length"); /* Updating uniform */
+
+ face_mod = (do_occlude_wire) ? 0.0f : 1.0f;
+
+ if (do_occlude_wire) {
+ geom = DRW_cache_surface_get(ob);
+ DRW_shgroup_call_add(stl->g_data->depth_shgrp_hidden_wire, geom, ob->obmat);
+ }
+
+ if (fnormals_do) {
+ geom = DRW_cache_face_centers_get(ob);
+ DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat);
+ }
+
+ if (vnormals_do) {
+ geom = DRW_cache_verts_get(ob);
+ DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
+ }
+
+ if (lnormals_do) {
+ geom = DRW_cache_surface_verts_get(ob);
+ DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geom, ob->obmat);
+ }
+
+ if ((v3d->flag & V3D_ZBUF_SELECT) == 0) {
+ edit_mesh_add_ob_to_pass(scene, ob, stl->g_data->face_occluded_shgrp, stl->g_data->ledges_occluded_shgrp,
+ stl->g_data->lverts_occluded_shgrp, stl->g_data->facedot_occluded_shgrp, stl->g_data->facefill_occluded_shgrp);
+ }
+ else {
+ edit_mesh_add_ob_to_pass(scene, ob, stl->g_data->face_overlay_shgrp, stl->g_data->ledges_overlay_shgrp,
+ stl->g_data->lverts_overlay_shgrp, stl->g_data->facedot_overlay_shgrp, NULL);
+ }
+ }
+ }
+}
+
+static void EDIT_MESH_draw_scene(void *vedata)
+{
+ EDIT_MESH_PassList *psl = ((EDIT_MESH_Data *)vedata)->psl;
+ EDIT_MESH_FramebufferList *fbl = ((EDIT_MESH_Data *)vedata)->fbl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ DRW_draw_pass(psl->depth_hidden_wire);
+
+ if (psl->edit_face_occluded) {
+ float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* render facefill */
+ DRW_draw_pass(psl->facefill_occlude);
+
+ /* Render wires on a separate framebuffer */
+ DRW_framebuffer_bind(fbl->occlude_wire_fb);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ DRW_draw_pass(psl->normals);
+ DRW_draw_pass(psl->edit_face_occluded);
+
+ /* detach textures */
+ DRW_framebuffer_texture_detach(dtxl->depth);
+
+ /* Combine with scene buffer */
+ DRW_framebuffer_bind(dfbl->default_fb);
+ DRW_draw_pass(psl->mix_occlude);
+
+ /* reattach */
+ DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ }
+ else {
+ DRW_draw_pass(psl->normals);
+ DRW_draw_pass(psl->edit_face_overlay);
+ }
+}
+
+void EDIT_MESH_collection_settings_create(IDProperty *properties)
+{
+ BLI_assert(properties &&
+ properties->type == IDP_GROUP &&
+ properties->subtype == IDP_GROUP_SUB_MODE_EDIT);
+ BKE_collection_engine_property_add_int(properties, "show_occlude_wire", false);
+ BKE_collection_engine_property_add_int(properties, "face_normals_show", false);
+ BKE_collection_engine_property_add_int(properties, "vert_normals_show", false);
+ BKE_collection_engine_property_add_int(properties, "loop_normals_show", false);
+ BKE_collection_engine_property_add_float(properties, "normals_length", 0.1);
+ BKE_collection_engine_property_add_float(properties, "backwire_opacity", 0.5);
+}
+
+static void EDIT_MESH_engine_free(void)
+{
+ if (e_data.overlay_tri_sh)
+ DRW_shader_free(e_data.overlay_tri_sh);
+ if (e_data.overlay_tri_fast_sh)
+ DRW_shader_free(e_data.overlay_tri_fast_sh);
+ if (e_data.overlay_tri_vcol_sh)
+ DRW_shader_free(e_data.overlay_tri_vcol_sh);
+ if (e_data.overlay_tri_vcol_fast_sh)
+ DRW_shader_free(e_data.overlay_tri_vcol_fast_sh);
+ if (e_data.overlay_edge_sh)
+ DRW_shader_free(e_data.overlay_edge_sh);
+ if (e_data.overlay_edge_vcol_sh)
+ DRW_shader_free(e_data.overlay_edge_vcol_sh);
+ if (e_data.overlay_vert_sh)
+ DRW_shader_free(e_data.overlay_vert_sh);
+ if (e_data.overlay_facedot_sh)
+ DRW_shader_free(e_data.overlay_facedot_sh);
+ if (e_data.overlay_mix_sh)
+ DRW_shader_free(e_data.overlay_mix_sh);
+ if (e_data.overlay_facefill_sh)
+ DRW_shader_free(e_data.overlay_facefill_sh);
+ if (e_data.normals_face_sh)
+ DRW_shader_free(e_data.normals_face_sh);
+ if (e_data.normals_sh)
+ DRW_shader_free(e_data.normals_sh);
+}
+
+DrawEngineType draw_engine_edit_mesh_type = {
+ NULL, NULL,
+ N_("EditMeshMode"),
+ &EDIT_MESH_engine_init,
+ &EDIT_MESH_engine_free,
+ &EDIT_MESH_cache_init,
+ &EDIT_MESH_cache_populate,
+ NULL,
+ NULL,
+ &EDIT_MESH_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c
new file mode 100644
index 00000000000..098dca7ac38
--- /dev/null
+++ b/source/blender/draw/modes/edit_metaball_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_metaball_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_METABALL_engine_init() to
+ * initialize most of them and EDIT_METABALL_cache_init()
+ * for EDIT_METABALL_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct EDIT_METABALL_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_METABALL_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_METABALL_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_METABALL_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_METABALL_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_METABALL_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_METABALL_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_METABALL_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} EDIT_METABALL_StorageList;
+
+typedef struct EDIT_METABALL_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_METABALL_FramebufferList *fbl;
+ EDIT_METABALL_TextureList *txl;
+ EDIT_METABALL_PassList *psl;
+ EDIT_METABALL_StorageList *stl;
+} EDIT_METABALL_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_METABALL_engine_init();
+ * free in EDIT_METABALL_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_METABALL_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_METABALL_engine_init(void *vedata)
+{
+ EDIT_METABALL_TextureList *txl = ((EDIT_METABALL_Data *)vedata)->txl;
+ EDIT_METABALL_FramebufferList *fbl = ((EDIT_METABALL_Data *)vedata)->fbl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_METABALL_cache_init(void *vedata)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.0f, 1.0f, 0.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_METABALL_cache_finish(void *vedata)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_METABALL_draw_scene(void *vedata)
+{
+ EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+ EDIT_METABALL_FramebufferList *fbl = ((EDIT_METABALL_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_METABALL_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_METABALL_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_edit_metaball_type = {
+ NULL, NULL,
+ N_("EditMetaballMode"),
+ &EDIT_METABALL_engine_init,
+ &EDIT_METABALL_engine_free,
+ &EDIT_METABALL_cache_init,
+ &EDIT_METABALL_cache_populate,
+ &EDIT_METABALL_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_METABALL_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_surface_mode.c b/source/blender/draw/modes/edit_surface_mode.c
new file mode 100644
index 00000000000..fcae505a673
--- /dev/null
+++ b/source/blender/draw/modes/edit_surface_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_surface_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_SURFACE_engine_init() to
+ * initialize most of them and EDIT_SURFACE_cache_init()
+ * for EDIT_SURFACE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct EDIT_SURFACE_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_SURFACE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_SURFACE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_SURFACE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_SURFACE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_SURFACE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_SURFACE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_SURFACE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} EDIT_SURFACE_StorageList;
+
+typedef struct EDIT_SURFACE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_SURFACE_FramebufferList *fbl;
+ EDIT_SURFACE_TextureList *txl;
+ EDIT_SURFACE_PassList *psl;
+ EDIT_SURFACE_StorageList *stl;
+} EDIT_SURFACE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_SURFACE_engine_init();
+ * free in EDIT_SURFACE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_SURFACE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_SURFACE_engine_init(void *vedata)
+{
+ EDIT_SURFACE_TextureList *txl = ((EDIT_SURFACE_Data *)vedata)->txl;
+ EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_SURFACE_cache_init(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.0f, 0.0f, 1.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_SURFACE_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_SURFACE_cache_finish(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_StorageList *stl = ((EDIT_SURFACE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_SURFACE_draw_scene(void *vedata)
+{
+ EDIT_SURFACE_PassList *psl = ((EDIT_SURFACE_Data *)vedata)->psl;
+ EDIT_SURFACE_FramebufferList *fbl = ((EDIT_SURFACE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_SURFACE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_SURFACE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_edit_surface_type = {
+ NULL, NULL,
+ N_("EditSurfaceMode"),
+ &EDIT_SURFACE_engine_init,
+ &EDIT_SURFACE_engine_free,
+ &EDIT_SURFACE_cache_init,
+ &EDIT_SURFACE_cache_populate,
+ &EDIT_SURFACE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_SURFACE_draw_scene
+};
diff --git a/source/blender/draw/modes/edit_text_mode.c b/source/blender/draw/modes/edit_text_mode.c
new file mode 100644
index 00000000000..2a1b0d4e4ae
--- /dev/null
+++ b/source/blender/draw/modes/edit_text_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/edit_text_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use EDIT_TEXT_engine_init() to
+ * initialize most of them and EDIT_TEXT_cache_init()
+ * for EDIT_TEXT_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct EDIT_TEXT_PassList {
+ /* Declare all passes here and init them in
+ * EDIT_TEXT_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} EDIT_TEXT_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct EDIT_TEXT_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} EDIT_TEXT_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct EDIT_TEXT_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} EDIT_TEXT_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct EDIT_TEXT_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} EDIT_TEXT_StorageList;
+
+typedef struct EDIT_TEXT_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ EDIT_TEXT_FramebufferList *fbl;
+ EDIT_TEXT_TextureList *txl;
+ EDIT_TEXT_PassList *psl;
+ EDIT_TEXT_StorageList *stl;
+} EDIT_TEXT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in EDIT_TEXT_engine_init();
+ * free in EDIT_TEXT_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in EDIT_TEXT_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void EDIT_TEXT_engine_init(void *vedata)
+{
+ EDIT_TEXT_TextureList *txl = ((EDIT_TEXT_Data *)vedata)->txl;
+ EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void EDIT_TEXT_cache_init(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {1.0f, 0.0f, 0.0f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_TEXT_cache_populate(void *vedata, Object *ob)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void EDIT_TEXT_cache_finish(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_StorageList *stl = ((EDIT_TEXT_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void EDIT_TEXT_draw_scene(void *vedata)
+{
+ EDIT_TEXT_PassList *psl = ((EDIT_TEXT_Data *)vedata)->psl;
+ EDIT_TEXT_FramebufferList *fbl = ((EDIT_TEXT_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void EDIT_TEXT_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void EDIT_TEXT_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_edit_text_type = {
+ NULL, NULL,
+ N_("EditTextMode"),
+ &EDIT_TEXT_engine_init,
+ &EDIT_TEXT_engine_free,
+ &EDIT_TEXT_cache_init,
+ &EDIT_TEXT_cache_populate,
+ &EDIT_TEXT_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &EDIT_TEXT_draw_scene
+};
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
new file mode 100644
index 00000000000..5a9582bd319
--- /dev/null
+++ b/source/blender/draw/modes/object_mode.c
@@ -0,0 +1,1061 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/object_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_userdef_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_world_types.h"
+
+#include "BKE_camera.h"
+#include "BKE_global.h"
+
+#include "ED_view3d.h"
+#include "ED_view3d.h"
+
+#include "GPU_shader.h"
+
+#include "UI_resources.h"
+
+#include "draw_mode_engines.h"
+#include "draw_common.h"
+
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern GlobalsUboStorage ts;
+
+extern char datatoc_object_outline_resolve_frag_glsl[];
+extern char datatoc_object_outline_detect_frag_glsl[];
+extern char datatoc_object_outline_expand_frag_glsl[];
+extern char datatoc_object_grid_frag_glsl[];
+extern char datatoc_object_grid_vert_glsl[];
+extern char datatoc_common_globals_lib_glsl[];
+
+/* *********** LISTS *********** */
+/* keep it under MAX_PASSES */
+typedef struct OBJECT_PassList {
+ struct DRWPass *non_meshes;
+ struct DRWPass *ob_center;
+ struct DRWPass *outlines;
+ struct DRWPass *outlines_search;
+ struct DRWPass *outlines_expand;
+ struct DRWPass *outlines_fade1;
+ struct DRWPass *outlines_fade2;
+ struct DRWPass *outlines_fade3;
+ struct DRWPass *outlines_fade4;
+ struct DRWPass *outlines_fade5;
+ struct DRWPass *outlines_resolve;
+ struct DRWPass *grid;
+ struct DRWPass *bone_solid;
+ struct DRWPass *bone_wire;
+} OBJECT_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct OBJECT_FramebufferList {
+ struct GPUFrameBuffer *outlines;
+ struct GPUFrameBuffer *blur;
+} OBJECT_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct OBJECT_TextureList {
+ struct GPUTexture *outlines_depth_tx;
+ struct GPUTexture *outlines_color_tx;
+ struct GPUTexture *outlines_blur_tx;
+} OBJECT_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct OBJECT_StorageList {
+ struct g_data *g_data;
+} OBJECT_StorageList;
+
+typedef struct OBJECT_Data {
+ void *engine_type;
+ void *fbl;
+ void *txl;
+ OBJECT_PassList *psl;
+ void *stl;
+} OBJECT_Data;
+
+/* *********** STATIC *********** */
+
+typedef struct g_data{
+ /* Empties */
+ DRWShadingGroup *plain_axes;
+ DRWShadingGroup *cube;
+ DRWShadingGroup *circle;
+ DRWShadingGroup *sphere;
+ DRWShadingGroup *cone;
+ DRWShadingGroup *single_arrow;
+ DRWShadingGroup *single_arrow_line;
+ DRWShadingGroup *arrows;
+ DRWShadingGroup *axis_names;
+
+ /* Speaker */
+ DRWShadingGroup *speaker;
+
+ /* Lamps */
+ DRWShadingGroup *lamp_center;
+ DRWShadingGroup *lamp_center_group;
+ DRWShadingGroup *lamp_groundpoint;
+ DRWShadingGroup *lamp_groundline;
+ DRWShadingGroup *lamp_circle;
+ DRWShadingGroup *lamp_circle_shadow;
+ DRWShadingGroup *lamp_sunrays;
+ DRWShadingGroup *lamp_distance;
+ DRWShadingGroup *lamp_buflimit;
+ DRWShadingGroup *lamp_buflimit_points;
+ DRWShadingGroup *lamp_area;
+ DRWShadingGroup *lamp_hemi;
+ DRWShadingGroup *lamp_spot_cone;
+ DRWShadingGroup *lamp_spot_blend;
+ DRWShadingGroup *lamp_spot_pyramid;
+ DRWShadingGroup *lamp_spot_blend_rect;
+
+ /* Helpers */
+ DRWShadingGroup *relationship_lines;
+
+ /* Objects Centers */
+ DRWShadingGroup *center_active;
+ DRWShadingGroup *center_selected;
+ DRWShadingGroup *center_deselected;
+
+ /* Camera */
+ DRWShadingGroup *camera;
+ DRWShadingGroup *camera_tria;
+ DRWShadingGroup *camera_focus;
+ DRWShadingGroup *camera_clip;
+ DRWShadingGroup *camera_clip_points;
+ DRWShadingGroup *camera_mist;
+ DRWShadingGroup *camera_mist_points;
+
+ /* Outlines */
+ DRWShadingGroup *outlines_active;
+ DRWShadingGroup *outlines_active_group;
+ DRWShadingGroup *outlines_select;
+ DRWShadingGroup *outlines_select_group;
+ DRWShadingGroup *outlines_transform;
+
+} g_data; /* Transient data */
+
+static struct {
+ struct GPUShader *outline_resolve_sh;
+ struct GPUShader *outline_detect_sh;
+ struct GPUShader *outline_fade_sh;
+ struct GPUShader *grid_sh;
+ float camera_pos[3];
+ float grid_settings[5];
+ float grid_mat[4][4];
+ int grid_flag;
+ int zpos_flag;
+ int zneg_flag;
+} e_data = {NULL}; /* Engine data */
+
+
+enum {
+ SHOW_AXIS_X = (1 << 0),
+ SHOW_AXIS_Y = (1 << 1),
+ SHOW_AXIS_Z = (1 << 2),
+ SHOW_GRID = (1 << 3),
+ PLANE_XY = (1 << 4),
+ PLANE_XZ = (1 << 5),
+ PLANE_YZ = (1 << 6),
+ CLIP_ZPOS = (1 << 7),
+ CLIP_ZNEG = (1 << 8),
+};
+
+/* *********** FUNCTIONS *********** */
+
+static void OBJECT_engine_init(void *vedata)
+{
+ OBJECT_TextureList *txl = ((OBJECT_Data *)vedata)->txl;
+ OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
+
+ float *viewport_size = DRW_viewport_size_get();
+
+ DRWFboTexture tex[2] = {{&txl->outlines_depth_tx, DRW_BUF_DEPTH_24},
+ {&txl->outlines_color_tx, DRW_BUF_RGBA_8}};
+ DRW_framebuffer_init(&fbl->outlines,
+ (int)viewport_size[0], (int)viewport_size[1],
+ tex, 2);
+
+ DRWFboTexture blur_tex = {&txl->outlines_blur_tx, DRW_BUF_RGBA_8};
+ DRW_framebuffer_init(&fbl->blur,
+ (int)viewport_size[0], (int)viewport_size[1],
+ &blur_tex, 1);
+
+ if (!e_data.outline_resolve_sh) {
+ e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL);
+ }
+
+ if (!e_data.outline_detect_sh) {
+ e_data.outline_detect_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL);
+ }
+
+ if (!e_data.outline_fade_sh) {
+ e_data.outline_fade_sh = DRW_shader_create_fullscreen(datatoc_object_outline_expand_frag_glsl, NULL);
+ }
+
+ if (!e_data.grid_sh) {
+ e_data.grid_sh = DRW_shader_create_with_lib(datatoc_object_grid_vert_glsl, NULL,
+ datatoc_object_grid_frag_glsl,
+ datatoc_common_globals_lib_glsl, NULL);
+ }
+
+ {
+ /* Grid precompute */
+ float viewinvmat[4][4], winmat[4][4], invwinmat[4][4], viewmat[4][4];
+ const bContext *C = DRW_get_context();
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL);
+ float grid_res, offs;
+
+ const bool show_axis_x = v3d->gridflag & V3D_SHOW_X;
+ const bool show_axis_y = v3d->gridflag & V3D_SHOW_Y;
+ const bool show_axis_z = v3d->gridflag & V3D_SHOW_Z;
+ const bool show_floor = (v3d->gridflag & V3D_SHOW_FLOOR);
+
+ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+ DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV);
+
+ /* Setup camera pos */
+ copy_v3_v3(e_data.camera_pos, viewinvmat[3]);
+
+ /* if perps */
+ if (winmat[3][3] == 0.0f) {
+ float fov;
+ float viewvecs[2][4] = {
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+ /* invert the proj matrix */
+ invert_m4_m4(invwinmat, winmat);
+
+ /* convert the view vectors to view space */
+ for (int i = 0; i < 2; i++) {
+ mul_m4_v4(invwinmat, viewvecs[i]);
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* normalize */
+ }
+
+ fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f;
+ grid_res = fabsf(tanf(fov)) / grid_scale;
+
+ /* Grid matrix polygon offset (fix depth fighting) */
+ /* see ED_view3d_polygon_offset */
+ offs = winmat[3][2] * -0.0025f;
+
+ e_data.grid_flag = (1 << 4); /* XY plane */
+ if (show_axis_x)
+ e_data.grid_flag |= SHOW_AXIS_X;
+ if (show_axis_y)
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ if (show_floor)
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else {
+ float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
+ grid_res = viewdist / grid_scale;
+
+ /* Grid matrix polygon offset (fix depth fighting) */
+ /* see ED_view3d_polygon_offset */
+ offs = 0.00001f * viewdist;
+ if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
+ e_data.grid_flag = PLANE_YZ;
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ e_data.grid_flag |= SHOW_AXIS_Z;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ e_data.grid_flag = PLANE_XY;
+ e_data.grid_flag |= SHOW_AXIS_X;
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
+ e_data.grid_flag = PLANE_XZ;
+ e_data.grid_flag |= SHOW_AXIS_X;
+ e_data.grid_flag |= SHOW_AXIS_Z;
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ else { /* RV3D_VIEW_USER */
+ e_data.grid_flag = PLANE_XY;
+ if (show_axis_x)
+ e_data.grid_flag |= SHOW_AXIS_X;
+ if (show_axis_y)
+ e_data.grid_flag |= SHOW_AXIS_Y;
+ if (show_floor)
+ e_data.grid_flag |= SHOW_GRID;
+ }
+ }
+
+ /* Z axis if needed */
+ if (((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) && show_axis_z) {
+ e_data.zpos_flag = SHOW_AXIS_Z;
+
+ float zvec[4] = {0.0f, 0.0f, -1.0f, 0.0f};
+ mul_m4_v4(viewinvmat, zvec);
+
+ /* z axis : chose the most facing plane */
+ if (fabsf(zvec[0]) < fabsf(zvec[1])) {
+ e_data.zpos_flag |= PLANE_XZ;
+ }
+ else {
+ e_data.zpos_flag |= PLANE_YZ;
+ }
+
+ e_data.zneg_flag = e_data.zpos_flag;
+
+ /* Persp : If camera is below floor plane, we switch clipping
+ * Ortho : If eye vector is looking up, we switch clipping */
+ if (((winmat[3][3] == 0.0f) && (e_data.camera_pos[2] > 0.0f)) ||
+ ((winmat[3][3] != 0.0f) && (zvec[2] < 0.0f))) {
+ e_data.zpos_flag |= CLIP_ZPOS;
+ e_data.zneg_flag |= CLIP_ZNEG;
+ }
+ else {
+ e_data.zpos_flag |= CLIP_ZNEG;
+ e_data.zneg_flag |= CLIP_ZPOS;
+ }
+ }
+ else {
+ e_data.zneg_flag = e_data.zpos_flag = CLIP_ZNEG | CLIP_ZPOS;
+ }
+
+ winmat[3][2] -= offs;
+ mul_m4_m4m4(e_data.grid_mat, winmat, viewmat);
+
+ e_data.grid_settings[0] = v3d->far / 2.0f; /* gridDistance */
+ e_data.grid_settings[1] = grid_res; /* gridResolution */
+ e_data.grid_settings[2] = grid_scale; /* gridScale */
+ e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */
+ e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / log(v3d->gridsubdiv) : 0.0; /* 1/log(gridSubdiv) */
+ }
+}
+
+static void OBJECT_engine_free(void)
+{
+ if (e_data.outline_resolve_sh)
+ DRW_shader_free(e_data.outline_resolve_sh);
+ if (e_data.outline_detect_sh)
+ DRW_shader_free(e_data.outline_detect_sh);
+ if (e_data.outline_fade_sh)
+ DRW_shader_free(e_data.outline_fade_sh);
+ if (e_data.grid_sh)
+ DRW_shader_free(e_data.grid_sh);
+}
+
+static DRWShadingGroup *shgroup_outline(DRWPass *pass, const float col[4], struct GPUShader *sh)
+{
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+ return grp;
+}
+
+static void OBJECT_cache_init(void *vedata)
+{
+ OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
+ OBJECT_TextureList *txl = ((OBJECT_Data *)vedata)->txl;
+ OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_WIRE;
+ psl->outlines = DRW_pass_create("Outlines Pass", state);
+
+ struct GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* Select */
+ stl->g_data->outlines_select = shgroup_outline(psl->outlines, ts.colorSelect, sh);
+ stl->g_data->outlines_select_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh);
+
+ /* Transform */
+ stl->g_data->outlines_transform = shgroup_outline(psl->outlines, ts.colorTransform, sh);
+
+ /* Active */
+ stl->g_data->outlines_active = shgroup_outline(psl->outlines, ts.colorActive, sh);
+ stl->g_data->outlines_active_group = shgroup_outline(psl->outlines, ts.colorGroupActive, sh);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR;
+ struct Batch *quad = DRW_cache_fullscreen_quad_get();
+ static float alphaOcclu = 0.35f;
+ static float one = 1.0f;
+ static float alpha1 = 5.0f / 6.0f;
+ static float alpha2 = 4.0f / 5.0f;
+ static float alpha3 = 3.0f / 4.0f;
+ static float alpha4 = 2.0f / 3.0f;
+ static float alpha5 = 1.0f / 2.0f;
+ static bool bTrue = true;
+ static bool bFalse = false;
+
+ psl->outlines_search = DRW_pass_create("Outlines Expand Pass", state);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_buffer(grp, "sceneDepth", &dtxl->depth, 2);
+ DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &one, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bTrue, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_fade1 = DRW_pass_create("Outlines Fade 1 Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade1);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &alpha1, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_fade2 = DRW_pass_create("Outlines Fade 2 Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade2);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &alpha2, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_fade3 = DRW_pass_create("Outlines Fade 3 Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade3);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &alpha3, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_fade4 = DRW_pass_create("Outlines Fade 4 Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade4);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &alpha4, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+
+ psl->outlines_fade5 = DRW_pass_create("Outlines Fade 5 Pass", state);
+
+ grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade5);
+ DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
+ DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
+ DRW_shgroup_uniform_float(grp, "alpha", &alpha5, 1);
+ DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+
+ {
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND;
+ psl->outlines_resolve = DRW_pass_create("Outlines Resolve Pass", state);
+
+ struct Batch *quad = DRW_cache_fullscreen_quad_get();
+
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_sh, psl->outlines_resolve);
+ DRW_shgroup_uniform_buffer(grp, "outlineBluredColor", &txl->outlines_blur_tx, 0);
+ DRW_shgroup_call_add(grp, quad, NULL);
+ }
+
+ {
+ /* Grid pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->grid = DRW_pass_create("Infinite Grid Pass", state);
+
+ struct Batch *quad = DRW_cache_fullscreen_quad_get();
+ static float mat[4][4];
+ unit_m4(mat);
+
+ /* Create 3 quads to render ordered transparency Z axis */
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
+ DRW_shgroup_uniform_mat4(grp, "ViewProjectionOffsetMatrix", (float *)e_data.grid_mat);
+ DRW_shgroup_uniform_vec3(grp, "cameraPos", e_data.camera_pos, 1);
+ DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1);
+ DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", globals_ubo, 0);
+ DRW_shgroup_call_add(grp, quad, mat);
+
+ grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.grid_flag, 1);
+ DRW_shgroup_call_add(grp, quad, mat);
+
+ grp = DRW_shgroup_create(e_data.grid_sh, psl->grid);
+ DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zpos_flag, 1);
+ DRW_shgroup_call_add(grp, quad, mat);
+ }
+
+ {
+ /* Solid bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS;
+ psl->bone_solid = DRW_pass_create("Bone Solid Pass", state);
+ }
+
+ {
+ /* Wire bones */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+ psl->bone_wire = DRW_pass_create("Bone Wire Pass", state);
+ }
+
+ {
+ /* Non Meshes Pass (Camera, empties, lamps ...) */
+ struct Batch *geom;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_POINT;
+ state |= DRW_STATE_WIRE;
+ psl->non_meshes = DRW_pass_create("Non Meshes Pass", state);
+
+ /* Empties */
+ geom = DRW_cache_plain_axes_get();
+ stl->g_data->plain_axes = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_cube_get();
+ stl->g_data->cube = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_circle_get();
+ stl->g_data->circle = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_sphere_get();
+ stl->g_data->sphere = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_empty_cone_get();
+ stl->g_data->cone = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_arrow_get();
+ stl->g_data->single_arrow = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->single_arrow_line = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_arrows_get();
+ stl->g_data->arrows = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_axis_names_get();
+ stl->g_data->axis_names = shgroup_instance_axis_names(psl->non_meshes, geom);
+
+ /* Speaker */
+ geom = DRW_cache_speaker_get();
+ stl->g_data->speaker = shgroup_instance(psl->non_meshes, geom);
+
+ /* Camera */
+ geom = DRW_cache_camera_get();
+ stl->g_data->camera = shgroup_camera_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_camera_tria_get();
+ stl->g_data->camera_tria = shgroup_camera_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_plain_axes_get();
+ stl->g_data->camera_focus = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->camera_clip = shgroup_distance_lines_instance(psl->non_meshes, geom);
+ stl->g_data->camera_mist = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_endpoints_get();
+ stl->g_data->camera_clip_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+ stl->g_data->camera_mist_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ /* Lamps */
+ /* TODO
+ * for now we create multiple times the same VBO with only lamp center coordinates
+ * but ideally we would only create it once */
+
+ /* start with buflimit because we don't want stipples */
+ geom = DRW_cache_single_line_get();
+ stl->g_data->lamp_buflimit = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ stl->g_data->lamp_center = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorLampNoAlpha, &ts.sizeLampCenter);
+ stl->g_data->lamp_center_group = shgroup_dynpoints_uniform_color(psl->non_meshes, ts.colorGroup, &ts.sizeLampCenter);
+
+ geom = DRW_cache_lamp_get();
+ stl->g_data->lamp_circle = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+ stl->g_data->lamp_circle_shadow = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircleShadow);
+
+ geom = DRW_cache_lamp_sunrays_get();
+ stl->g_data->lamp_sunrays = shgroup_instance_screenspace(psl->non_meshes, geom, &ts.sizeLampCircle);
+
+ stl->g_data->lamp_groundline = shgroup_groundlines_uniform_color(psl->non_meshes, ts.colorLamp);
+ stl->g_data->lamp_groundpoint = shgroup_groundpoints_uniform_color(psl->non_meshes, ts.colorLamp);
+
+ geom = DRW_cache_lamp_area_get();
+ stl->g_data->lamp_area = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_hemi_get();
+ stl->g_data->lamp_hemi = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_get();
+ stl->g_data->lamp_distance = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_single_line_endpoints_get();
+ stl->g_data->lamp_buflimit_points = shgroup_distance_lines_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_spot_get();
+ stl->g_data->lamp_spot_cone = shgroup_spot_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_circle_get();
+ stl->g_data->lamp_spot_blend = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_lamp_spot_square_get();
+ stl->g_data->lamp_spot_pyramid = shgroup_instance(psl->non_meshes, geom);
+
+ geom = DRW_cache_square_get();
+ stl->g_data->lamp_spot_blend_rect = shgroup_instance(psl->non_meshes, geom);
+
+ /* Relationship Lines */
+ stl->g_data->relationship_lines = shgroup_dynlines_uniform_color(psl->non_meshes, ts.colorWire);
+ DRW_shgroup_state_set(stl->g_data->relationship_lines, DRW_STATE_STIPPLE_3);
+ }
+
+ {
+ /* Object Center pass grouped by State */
+ DRWShadingGroup *grp;
+ static float outlineWidth, size;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
+ psl->ob_center = DRW_pass_create("Obj Center Pass", state);
+
+ outlineWidth = 1.0f * U.pixelsize;
+ size = U.obcenter_dia * U.pixelsize + outlineWidth;
+
+ struct GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+
+ /* Active */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_float(grp, "size", &size, 1);
+ DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorActive, 1);
+ DRW_shgroup_uniform_vec4(grp, "outlineColor", ts.colorOutline, 1);
+ stl->g_data->center_active = grp;
+
+ /* Select */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorSelect, 1);
+ stl->g_data->center_selected = grp;
+
+ /* Deselect */
+ grp = DRW_shgroup_point_batch_create(sh, psl->ob_center);
+ DRW_shgroup_uniform_vec4(grp, "color", ts.colorDeselect, 1);
+ stl->g_data->center_deselected = grp;
+ }
+}
+
+static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl)
+{
+ Lamp *la = ob->data;
+ float *color;
+ int theme_id = DRW_object_wire_theme_get(ob, sl, &color);
+ static float zero = 0.0f;
+
+ float **la_mats = (float **)DRW_object_engine_data_get(ob, &draw_engine_object_type);
+ if (*la_mats == NULL) {
+ /* we need 2 matrices */
+ *la_mats = MEM_mallocN(sizeof(float) * 16 * 2, "Lamp Object Mode Matrices");
+ }
+
+ float (*shapemat)[4], (*spotblendmat)[4];
+ shapemat = (float (*)[4])(*la_mats);
+ spotblendmat = (float (*)[4])(*la_mats + 16);
+
+ /* Don't draw the center if it's selected or active */
+ if (theme_id == TH_GROUP)
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_center_group, ob->obmat[3]);
+ else if (theme_id == TH_LAMP)
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_center, ob->obmat[3]);
+
+ /* First circle */
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_circle, ob->obmat[3], color);
+
+ /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
+ if (la->type != LA_HEMI) {
+ if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_circle_shadow, ob->obmat[3], color);
+ }
+ }
+
+ /* Distance */
+ if (ELEM(la->type, LA_HEMI, LA_SUN, LA_AREA)) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_distance, color, &zero, &la->dist, ob->obmat);
+ }
+
+ copy_m4_m4(shapemat, ob->obmat);
+
+ if (la->type == LA_SUN) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_sunrays, ob->obmat[3], color);
+ }
+ else if (la->type == LA_SPOT) {
+ float size[3], sizemat[4][4];
+ static float one = 1.0f;
+ float blend = 1.0f - pow2f(la->spotblend);
+
+ size[0] = size[1] = sinf(la->spotsize * 0.5f) * la->dist;
+ size[2] = cosf(la->spotsize * 0.5f) * la->dist;
+
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(shapemat, ob->obmat, sizemat);
+
+ size[0] = size[1] = blend; size[2] = 1.0f;
+ size_to_mat4(sizemat, size);
+ translate_m4(sizemat, 0.0f, 0.0f, -1.0f);
+ rotate_m4(sizemat, 'X', M_PI / 2.0f);
+ mul_m4_m4m4(spotblendmat, shapemat, sizemat);
+
+ if (la->mode & LA_SQUARE) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_pyramid, color, &one, shapemat);
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != 1.0f) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend_rect, color, &one, spotblendmat);
+ }
+ }
+ else {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_cone, color, shapemat);
+
+ /* hide line if it is zero size or overlaps with outer border,
+ * previously it adjusted to always to show it but that seems
+ * confusing because it doesn't show the actual blend size */
+ if (blend != 0.0f && blend != 1.0f) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_spot_blend, color, &one, spotblendmat);
+ }
+ }
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_buflimit, color, &la->clipsta, &la->clipend, ob->obmat);
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_buflimit_points, color, &la->clipsta, &la->clipend, ob->obmat);
+ }
+ else if (la->type == LA_HEMI) {
+ static float hemisize = 2.0f;
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_hemi, color, &hemisize, shapemat);
+ }
+ else if (la->type == LA_AREA) {
+ float size[3] = {1.0f, 1.0f, 1.0f}, sizemat[4][4];
+
+ if (la->area_shape == LA_AREA_RECT) {
+ size[1] = la->area_sizey / la->area_size;
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(shapemat, shapemat, sizemat);
+ }
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_area, color, &la->area_size, shapemat);
+ }
+
+ /* Line and point going to the ground */
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_groundline, ob->obmat[3]);
+ DRW_shgroup_dynamic_call_add(stl->g_data->lamp_groundpoint, ob->obmat[3]);
+}
+
+static void DRW_shgroup_camera(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl)
+{
+ const struct bContext *C = DRW_get_context();
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+
+ Camera *cam = ob->data;
+ const bool is_active = (ob == v3d->camera);
+ float *color;
+ DRW_object_wire_theme_get(ob, sl, &color);
+
+ float vec[4][3], asp[2], shift[2], scale[3], drawsize;
+
+ scale[0] = 1.0f / len_v3(ob->obmat[0]);
+ scale[1] = 1.0f / len_v3(ob->obmat[1]);
+ scale[2] = 1.0f / len_v3(ob->obmat[2]);
+
+ BKE_camera_view_frame_ex(scene, cam, cam->drawsize, false, scale,
+ asp, shift, &drawsize, vec);
+
+ // /* Frame coords */
+ copy_v2_v2(cam->drwcorners[0], vec[0]);
+ copy_v2_v2(cam->drwcorners[1], vec[1]);
+ copy_v2_v2(cam->drwcorners[2], vec[2]);
+ copy_v2_v2(cam->drwcorners[3], vec[3]);
+
+ /* depth */
+ cam->drwdepth = vec[0][2];
+
+ /* tria */
+ cam->drwtria[0][0] = shift[0] + ((0.7f * drawsize) * scale[0]);
+ cam->drwtria[0][1] = shift[1] + ((drawsize * (asp[1] + 0.1f)) * scale[1]);
+ cam->drwtria[1][0] = shift[0];
+ cam->drwtria[1][1] = shift[1] + ((1.1f * drawsize * (asp[1] + 0.7f)) * scale[1]);
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+
+ /* Active cam */
+ if (is_active) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_tria, color, cam->drwcorners, &cam->drwdepth, cam->drwtria, ob->obmat);
+ }
+
+ /* draw the rest in normalize object space */
+ copy_m4_m4(cam->drwnormalmat, ob->obmat);
+ normalize_m4(cam->drwnormalmat);
+
+ if (cam->flag & CAM_SHOWLIMITS) {
+ static float col[3] = {0.5f, 0.5f, 0.25f}, col_hi[3] = {1.0f, 1.0f, 0.5f};
+ float sizemat[4][4], size[3] = {1.0f, 1.0f, 0.0f};
+ float focusdist = BKE_camera_object_dof_distance(ob);
+
+ copy_m4_m4(cam->drwfocusmat, cam->drwnormalmat);
+ translate_m4(cam->drwfocusmat, 0.0f, 0.0f, -focusdist);
+ size_to_mat4(sizemat, size);
+ mul_m4_m4m4(cam->drwfocusmat, cam->drwfocusmat, sizemat);
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_focus, (is_active ? col_hi : col), &cam->drawsize, cam->drwfocusmat);
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_clip, color, &cam->clipsta, &cam->clipend, cam->drwnormalmat);
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_clip_points, (is_active ? col_hi : col), &cam->clipsta, &cam->clipend, cam->drwnormalmat);
+ }
+
+ if (cam->flag & CAM_SHOWMIST) {
+ World *world = scene->world;
+
+ if (world) {
+ static float col[3] = {0.5f, 0.5f, 0.5f}, col_hi[3] = {1.0f, 1.0f, 1.0f};
+ world->mistend = world->miststa + world->mistdist;
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_mist, color, &world->miststa, &world->mistend, cam->drwnormalmat);
+ DRW_shgroup_dynamic_call_add(stl->g_data->camera_mist_points, (is_active ? col_hi : col), &world->miststa, &world->mistend, cam->drwnormalmat);
+ }
+ }
+}
+
+static void DRW_shgroup_empty(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl)
+{
+ float *color;
+ DRW_object_wire_theme_get(ob, sl, &color);
+
+ switch (ob->empty_drawtype) {
+ case OB_PLAINAXES:
+ DRW_shgroup_dynamic_call_add(stl->g_data->plain_axes, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_SINGLE_ARROW:
+ DRW_shgroup_dynamic_call_add(stl->g_data->single_arrow, color, &ob->empty_drawsize, ob->obmat);
+ DRW_shgroup_dynamic_call_add(stl->g_data->single_arrow_line, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CUBE:
+ DRW_shgroup_dynamic_call_add(stl->g_data->cube, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_CIRCLE:
+ DRW_shgroup_dynamic_call_add(stl->g_data->circle, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_SPHERE:
+ DRW_shgroup_dynamic_call_add(stl->g_data->sphere, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_EMPTY_CONE:
+ DRW_shgroup_dynamic_call_add(stl->g_data->cone, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ case OB_ARROWS:
+ DRW_shgroup_dynamic_call_add(stl->g_data->arrows, color, &ob->empty_drawsize, ob->obmat);
+ DRW_shgroup_dynamic_call_add(stl->g_data->axis_names, color, &ob->empty_drawsize, ob->obmat);
+ break;
+ }
+}
+
+static void DRW_shgroup_speaker(OBJECT_StorageList *stl, Object *ob, SceneLayer *sl)
+{
+ float *color;
+ static float one = 1.0f;
+ DRW_object_wire_theme_get(ob, sl, &color);
+
+ DRW_shgroup_dynamic_call_add(stl->g_data->speaker, color, &one, ob->obmat);
+}
+
+static void DRW_shgroup_relationship_lines(OBJECT_StorageList *stl, Object *ob)
+{
+ if (ob->parent) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->relationship_lines, ob->obmat[3]);
+ DRW_shgroup_dynamic_call_add(stl->g_data->relationship_lines, ob->parent->obmat[3]);
+ }
+}
+
+static void DRW_shgroup_object_center(OBJECT_StorageList *stl, Object *ob)
+{
+ if ((ob->base_flag & BASE_SELECTED) != 0) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->center_selected, ob->obmat[3]);
+ }
+ else if (0) {
+ DRW_shgroup_dynamic_call_add(stl->g_data->center_deselected, ob->obmat[3]);
+ }
+}
+
+static void OBJECT_cache_populate(void *vedata, Object *ob)
+{
+ OBJECT_StorageList *stl = ((OBJECT_Data *)vedata)->stl;
+ const struct bContext *C = DRW_get_context();
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ //CollectionEngineSettings *ces_mode_ob = BKE_object_collection_engine_get(ob, COLLECTION_MODE_OBJECT, "");
+
+ //bool do_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ob, "show_wire");
+ bool do_outlines = ((ob->base_flag & BASE_SELECTED) != 0);
+
+ switch (ob->type) {
+ case OB_MESH:
+ {
+ Object *obedit = scene->obedit;
+ int theme_id = DRW_object_wire_theme_get(ob, sl, NULL);
+ if (ob != obedit) {
+ if (do_outlines) {
+ struct Batch *geom = DRW_cache_surface_get(ob);
+ switch (theme_id) {
+ case TH_ACTIVE:
+ DRW_shgroup_call_add(stl->g_data->outlines_active, geom, ob->obmat);
+ break;
+ case TH_SELECT:
+ DRW_shgroup_call_add(stl->g_data->outlines_select, geom, ob->obmat);
+ break;
+ case TH_GROUP_ACTIVE:
+ DRW_shgroup_call_add(stl->g_data->outlines_select_group, geom, ob->obmat);
+ break;
+ case TH_TRANSFORM:
+ DRW_shgroup_call_add(stl->g_data->outlines_transform, geom, ob->obmat);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case OB_LAMP:
+ DRW_shgroup_lamp(stl, ob, sl);
+ break;
+ case OB_CAMERA:
+ DRW_shgroup_camera(stl, ob, sl);
+ break;
+ case OB_EMPTY:
+ DRW_shgroup_empty(stl, ob, sl);
+ break;
+ case OB_SPEAKER:
+ DRW_shgroup_speaker(stl, ob, sl);
+ break;
+ case OB_ARMATURE:
+ {
+ bArmature *arm = ob->data;
+ if (arm->edbo == NULL) {
+ DRW_shgroup_armature_object(ob, sl, ((OBJECT_Data *)vedata)->psl->bone_solid,
+ ((OBJECT_Data *)vedata)->psl->bone_wire,
+ stl->g_data->relationship_lines);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ DRW_shgroup_object_center(stl, ob);
+ DRW_shgroup_relationship_lines(stl, ob);
+}
+
+static void OBJECT_draw_scene(void *vedata)
+{
+
+ OBJECT_PassList *psl = ((OBJECT_Data *)vedata)->psl;
+ OBJECT_FramebufferList *fbl = ((OBJECT_Data *)vedata)->fbl;
+ OBJECT_TextureList *txl = ((OBJECT_Data *)vedata)->txl;
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ /* Render filled polygon on a separate framebuffer */
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
+ DRW_draw_pass(psl->outlines);
+
+ /* detach textures */
+ DRW_framebuffer_texture_detach(txl->outlines_depth_tx);
+
+ /* Search outline pixels */
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_search);
+
+ /* Expand and fade gradually */
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_draw_pass(psl->outlines_expand);
+
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_fade1);
+
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_draw_pass(psl->outlines_fade2);
+
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_fade3);
+
+ DRW_framebuffer_bind(fbl->outlines);
+ DRW_draw_pass(psl->outlines_fade4);
+
+ DRW_framebuffer_bind(fbl->blur);
+ DRW_draw_pass(psl->outlines_fade5);
+
+ /* reattach */
+ DRW_framebuffer_texture_attach(fbl->outlines, txl->outlines_depth_tx, 0);
+ DRW_framebuffer_bind(dfbl->default_fb);
+
+ /* This needs to be drawn after the oultine */
+ DRW_draw_pass(psl->bone_wire);
+ DRW_draw_pass(psl->bone_solid);
+ DRW_draw_pass(psl->non_meshes);
+ DRW_draw_pass(psl->ob_center);
+ DRW_draw_pass(psl->grid);
+
+ /* Combine with scene buffer last */
+ DRW_draw_pass(psl->outlines_resolve);
+}
+
+void OBJECT_collection_settings_create(IDProperty *props)
+{
+ BLI_assert(props &&
+ props->type == IDP_GROUP &&
+ props->subtype == IDP_GROUP_SUB_MODE_OBJECT);
+ BKE_collection_engine_property_add_int(props, "show_wire", false);
+ BKE_collection_engine_property_add_int(props, "show_backface_culling", false);
+}
+
+DrawEngineType draw_engine_object_type = {
+ NULL, NULL,
+ N_("ObjectMode"),
+ &OBJECT_engine_init,
+ &OBJECT_engine_free,
+ &OBJECT_cache_init,
+ &OBJECT_cache_populate,
+ NULL,
+ NULL,
+ &OBJECT_draw_scene
+};
diff --git a/source/blender/draw/modes/paint_texture_mode.c b/source/blender/draw/modes/paint_texture_mode.c
new file mode 100644
index 00000000000..9d620e0ce25
--- /dev/null
+++ b/source/blender/draw/modes/paint_texture_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/paint_texture_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PAINT_TEXTURE_engine_init() to
+ * initialize most of them and PAINT_TEXTURE_cache_init()
+ * for PAINT_TEXTURE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct PAINT_TEXTURE_PassList {
+ /* Declare all passes here and init them in
+ * PAINT_TEXTURE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} PAINT_TEXTURE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct PAINT_TEXTURE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PAINT_TEXTURE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct PAINT_TEXTURE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PAINT_TEXTURE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct PAINT_TEXTURE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} PAINT_TEXTURE_StorageList;
+
+typedef struct PAINT_TEXTURE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PAINT_TEXTURE_FramebufferList *fbl;
+ PAINT_TEXTURE_TextureList *txl;
+ PAINT_TEXTURE_PassList *psl;
+ PAINT_TEXTURE_StorageList *stl;
+} PAINT_TEXTURE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PAINT_TEXTURE_engine_init();
+ * free in PAINT_TEXTURE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in PAINT_TEXTURE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PAINT_TEXTURE_engine_init(void *vedata)
+{
+ PAINT_TEXTURE_TextureList *txl = ((PAINT_TEXTURE_Data *)vedata)->txl;
+ PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PAINT_TEXTURE_cache_init(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PAINT_TEXTURE_cache_finish(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PAINT_TEXTURE_draw_scene(void *vedata)
+{
+ PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
+ PAINT_TEXTURE_FramebufferList *fbl = ((PAINT_TEXTURE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PAINT_TEXTURE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PAINT_TEXTURE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_paint_texture_type = {
+ NULL, NULL,
+ N_("PaintTextureMode"),
+ &PAINT_TEXTURE_engine_init,
+ &PAINT_TEXTURE_engine_free,
+ &PAINT_TEXTURE_cache_init,
+ &PAINT_TEXTURE_cache_populate,
+ &PAINT_TEXTURE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PAINT_TEXTURE_draw_scene
+};
diff --git a/source/blender/draw/modes/paint_vertex_mode.c b/source/blender/draw/modes/paint_vertex_mode.c
new file mode 100644
index 00000000000..b3b32a4d6e9
--- /dev/null
+++ b/source/blender/draw/modes/paint_vertex_mode.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/paint_vertex_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PAINT_VERTEX_engine_init() to
+ * initialize most of them and PAINT_VERTEX_cache_init()
+ * for PAINT_VERTEX_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct PAINT_VERTEX_PassList {
+ /* Declare all passes here and init them in
+ * PAINT_VERTEX_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} PAINT_VERTEX_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct PAINT_VERTEX_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PAINT_VERTEX_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct PAINT_VERTEX_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PAINT_VERTEX_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct PAINT_VERTEX_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} PAINT_VERTEX_StorageList;
+
+typedef struct PAINT_VERTEX_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PAINT_VERTEX_FramebufferList *fbl;
+ PAINT_VERTEX_TextureList *txl;
+ PAINT_VERTEX_PassList *psl;
+ PAINT_VERTEX_StorageList *stl;
+} PAINT_VERTEX_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PAINT_VERTEX_engine_init();
+ * free in PAINT_VERTEX_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in PAINT_VERTEX_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PAINT_VERTEX_engine_init(void *vedata)
+{
+ PAINT_VERTEX_TextureList *txl = ((PAINT_VERTEX_Data *)vedata)->txl;
+ PAINT_VERTEX_FramebufferList *fbl = ((PAINT_VERTEX_Data *)vedata)->fbl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PAINT_VERTEX_cache_init(void *vedata)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PAINT_VERTEX_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PAINT_VERTEX_cache_finish(void *vedata)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_StorageList *stl = ((PAINT_VERTEX_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PAINT_VERTEX_draw_scene(void *vedata)
+{
+ PAINT_VERTEX_PassList *psl = ((PAINT_VERTEX_Data *)vedata)->psl;
+ PAINT_VERTEX_FramebufferList *fbl = ((PAINT_VERTEX_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PAINT_VERTEX_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PAINT_VERTEX_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_paint_vertex_type = {
+ NULL, NULL,
+ N_("PaintVertexMode"),
+ &PAINT_VERTEX_engine_init,
+ &PAINT_VERTEX_engine_free,
+ &PAINT_VERTEX_cache_init,
+ &PAINT_VERTEX_cache_populate,
+ &PAINT_VERTEX_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PAINT_VERTEX_draw_scene
+};
diff --git a/source/blender/draw/modes/paint_weight_mode.c b/source/blender/draw/modes/paint_weight_mode.c
new file mode 100644
index 00000000000..2d189e07fd2
--- /dev/null
+++ b/source/blender/draw/modes/paint_weight_mode.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/paint_weight_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* If needed, contains all global/Theme colors
+ * Add needed theme colors / values to DRW_globals_update() and update UBO
+ * Not needed for constant color. */
+extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
+extern struct GlobalsUboStorage ts; /* draw_common.c */
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PAINT_WEIGHT_engine_init() to
+ * initialize most of them and PAINT_WEIGHT_cache_init()
+ * for PAINT_WEIGHT_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct PAINT_WEIGHT_PassList {
+ /* Declare all passes here and init them in
+ * PAINT_WEIGHT_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} PAINT_WEIGHT_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct PAINT_WEIGHT_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PAINT_WEIGHT_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct PAINT_WEIGHT_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PAINT_WEIGHT_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct PAINT_WEIGHT_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} PAINT_WEIGHT_StorageList;
+
+typedef struct PAINT_WEIGHT_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PAINT_WEIGHT_FramebufferList *fbl;
+ PAINT_WEIGHT_TextureList *txl;
+ PAINT_WEIGHT_PassList *psl;
+ PAINT_WEIGHT_StorageList *stl;
+} PAINT_WEIGHT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PAINT_WEIGHT_engine_init();
+ * free in PAINT_WEIGHT_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in PAINT_WEIGHT_cache_populate() */
+ DRWShadingGroup *group;
+} g_data;
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PAINT_WEIGHT_engine_init(void *vedata)
+{
+ PAINT_WEIGHT_TextureList *txl = ((PAINT_WEIGHT_Data *)vedata)->txl;
+ PAINT_WEIGHT_FramebufferList *fbl = ((PAINT_WEIGHT_Data *)vedata)->fbl;
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PAINT_WEIGHT_cache_init(void *vedata)
+{
+ PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl;
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PAINT_WEIGHT_cache_populate(void *vedata, Object *ob)
+{
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PAINT_WEIGHT_cache_finish(void *vedata)
+{
+ PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl;
+ PAINT_WEIGHT_StorageList *stl = ((PAINT_WEIGHT_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PAINT_WEIGHT_draw_scene(void *vedata)
+{
+ PAINT_WEIGHT_PassList *psl = ((PAINT_WEIGHT_Data *)vedata)->psl;
+ PAINT_WEIGHT_FramebufferList *fbl = ((PAINT_WEIGHT_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PAINT_WEIGHT_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PAINT_WEIGHT_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_paint_weight_type = {
+ NULL, NULL,
+ N_("PaintWeightMode"),
+ &PAINT_WEIGHT_engine_init,
+ &PAINT_WEIGHT_engine_free,
+ &PAINT_WEIGHT_cache_init,
+ &PAINT_WEIGHT_cache_populate,
+ &PAINT_WEIGHT_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PAINT_WEIGHT_draw_scene
+};
diff --git a/source/blender/draw/modes/particle_mode.c b/source/blender/draw/modes/particle_mode.c
new file mode 100644
index 00000000000..aab9c41a233
--- /dev/null
+++ b/source/blender/draw/modes/particle_mode.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/particle_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use PARTICLE_engine_init() to
+ * initialize most of them and PARTICLE_cache_init()
+ * for PARTICLE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct PARTICLE_PassList {
+ /* Declare all passes here and init them in
+ * PARTICLE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} PARTICLE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct PARTICLE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} PARTICLE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct PARTICLE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} PARTICLE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct PARTICLE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} PARTICLE_StorageList;
+
+typedef struct PARTICLE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ PARTICLE_FramebufferList *fbl;
+ PARTICLE_TextureList *txl;
+ PARTICLE_PassList *psl;
+ PARTICLE_StorageList *stl;
+} PARTICLE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in PARTICLE_engine_init();
+ * free in PARTICLE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in PARTICLE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void PARTICLE_engine_init(void *vedata)
+{
+ PARTICLE_TextureList *txl = ((PARTICLE_Data *)vedata)->txl;
+ PARTICLE_FramebufferList *fbl = ((PARTICLE_Data *)vedata)->fbl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void PARTICLE_cache_init(void *vedata)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void PARTICLE_cache_populate(void *vedata, Object *ob)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void PARTICLE_cache_finish(void *vedata)
+{
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_StorageList *stl = ((PARTICLE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void PARTICLE_draw_scene(void *vedata)
+{
+
+ PARTICLE_PassList *psl = ((PARTICLE_Data *)vedata)->psl;
+ PARTICLE_FramebufferList *fbl = ((PARTICLE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void PARTICLE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void PARTICLE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_particle_type = {
+ NULL, NULL,
+ N_("ParticleMode"),
+ &PARTICLE_engine_init,
+ &PARTICLE_engine_free,
+ &PARTICLE_cache_init,
+ &PARTICLE_cache_populate,
+ &PARTICLE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &PARTICLE_draw_scene
+};
diff --git a/source/blender/draw/modes/pose_mode.c b/source/blender/draw/modes/pose_mode.c
new file mode 100644
index 00000000000..93514701010
--- /dev/null
+++ b/source/blender/draw/modes/pose_mode.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/pose_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use POSE_engine_init() to
+ * initialize most of them and POSE_cache_init()
+ * for POSE_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct POSE_PassList {
+ /* Declare all passes here and init them in
+ * POSE_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} POSE_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct POSE_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} POSE_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct POSE_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} POSE_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct POSE_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} POSE_StorageList;
+
+typedef struct POSE_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ POSE_FramebufferList *fbl;
+ POSE_TextureList *txl;
+ POSE_PassList *psl;
+ POSE_StorageList *stl;
+} POSE_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in POSE_engine_init();
+ * free in POSE_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in POSE_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void POSE_engine_init(void *vedata)
+{
+ POSE_TextureList *txl = ((POSE_Data *)vedata)->txl;
+ POSE_FramebufferList *fbl = ((POSE_Data *)vedata)->fbl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void POSE_cache_init(void *vedata)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void POSE_cache_populate(void *vedata, Object *ob)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void POSE_cache_finish(void *vedata)
+{
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_StorageList *stl = ((POSE_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void POSE_draw_scene(void *vedata)
+{
+
+ POSE_PassList *psl = ((POSE_Data *)vedata)->psl;
+ POSE_FramebufferList *fbl = ((POSE_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void POSE_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void POSE_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_pose_type = {
+ NULL, NULL,
+ N_("PoseMode"),
+ &POSE_engine_init,
+ &POSE_engine_free,
+ &POSE_cache_init,
+ &POSE_cache_populate,
+ &POSE_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &POSE_draw_scene
+};
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
new file mode 100644
index 00000000000..4b500c4d6fd
--- /dev/null
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/modes/sculpt_mode.c
+ * \ingroup draw
+ */
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+/* If builtin shaders are needed */
+#include "GPU_shader.h"
+
+#include "draw_common.h"
+
+#include "draw_mode_engines.h"
+
+/* *********** LISTS *********** */
+/* All lists are per viewport specific datas.
+ * They are all free when viewport changes engines
+ * or is free itself. Use SCULPT_engine_init() to
+ * initialize most of them and SCULPT_cache_init()
+ * for SCULPT_PassList */
+
+/* keep it under MAX_PASSES */
+typedef struct SCULPT_PassList {
+ /* Declare all passes here and init them in
+ * SCULPT_cache_init().
+ * Only contains (DRWPass *) */
+ struct DRWPass *pass;
+} SCULPT_PassList;
+
+/* keep it under MAX_BUFFERS */
+typedef struct SCULPT_FramebufferList {
+ /* Contains all framebuffer objects needed by this engine.
+ * Only contains (GPUFrameBuffer *) */
+ struct GPUFrameBuffer *fb;
+} SCULPT_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct SCULPT_TextureList {
+ /* Contains all framebuffer textures / utility textures
+ * needed by this engine. Only viewport specific textures
+ * (not per object). Only contains (GPUTexture *) */
+ struct GPUTexture *texture;
+} SCULPT_TextureList;
+
+/* keep it under MAX_STORAGE */
+typedef struct SCULPT_StorageList {
+ /* Contains any other memory block that the engine needs.
+ * Only directly MEM_(m/c)allocN'ed blocks because they are
+ * free with MEM_freeN() when viewport is freed.
+ * (not per object) */
+ struct CustomStruct *block;
+ struct g_data *g_data;
+} SCULPT_StorageList;
+
+typedef struct SCULPT_Data {
+ /* Struct returned by DRW_viewport_engine_data_get.
+ * If you don't use one of these, just make it a (void *) */
+ // void *fbl;
+ void *engine_type; /* Required */
+ SCULPT_FramebufferList *fbl;
+ SCULPT_TextureList *txl;
+ SCULPT_PassList *psl;
+ SCULPT_StorageList *stl;
+} SCULPT_Data;
+
+/* *********** STATIC *********** */
+
+static struct {
+ /* Custom shaders :
+ * Add sources to source/blender/draw/modes/shaders
+ * init in SCULPT_engine_init();
+ * free in SCULPT_engine_free(); */
+ struct GPUShader *custom_shader;
+} e_data = {NULL}; /* Engine data */
+
+typedef struct g_data {
+ /* This keeps the references of the shading groups for
+ * easy access in SCULPT_cache_populate() */
+ DRWShadingGroup *group;
+} g_data; /* Transient data */
+
+/* *********** FUNCTIONS *********** */
+
+/* Init Textures, Framebuffers, Storage and Shaders.
+ * It is called for every frames.
+ * (Optional) */
+static void SCULPT_engine_init(void *vedata)
+{
+ SCULPT_TextureList *txl = ((SCULPT_Data *)vedata)->txl;
+ SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ UNUSED_VARS(txl, fbl, stl);
+
+ /* Init Framebuffers like this: order is attachment order (for color texs) */
+ /*
+ * DRWFboTexture tex[2] = {{&txl->depth, DRW_BUF_DEPTH_24},
+ * {&txl->color, DRW_BUF_RGBA_8}};
+ */
+
+ /* DRW_framebuffer_init takes care of checking if
+ * the framebuffer is valid and has the right size*/
+ /*
+ * float *viewport_size = DRW_viewport_size_get();
+ * DRW_framebuffer_init(&fbl->occlude_wire_fb,
+ * (int)viewport_size[0], (int)viewport_size[1],
+ * tex, 2);
+ */
+
+ if (!e_data.custom_shader) {
+ e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+}
+
+/* Here init all passes and shading groups
+ * Assume that all Passes are NULL */
+static void SCULPT_cache_init(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ if (!stl->g_data) {
+ /* Alloc transient pointers */
+ stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
+ }
+
+ {
+ /* Create a pass */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND | DRW_STATE_WIRE;
+ psl->pass = DRW_pass_create("My Pass", state);
+
+ /* Create a shadingGroup using a function in draw_common.c or custom one */
+ /*
+ * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
+ * -- or --
+ * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+ */
+ stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
+
+ /* Uniforms need a pointer to it's value so be sure it's accessible at
+ * any given time (i.e. use static vars) */
+ static float color[4] = {0.2f, 0.5f, 0.3f, 1.0};
+ DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+ }
+
+}
+
+/* Add geometry to shadingGroups. Execute for each objects */
+static void SCULPT_cache_populate(void *vedata, Object *ob)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ UNUSED_VARS(psl, stl);
+
+ if (ob->type == OB_MESH) {
+ /* Get geometry cache */
+ struct Batch *geom = DRW_cache_surface_get(ob);
+
+ /* Add geom to a shading group */
+ DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+ }
+}
+
+/* Optional: Post-cache_populate callback */
+static void SCULPT_cache_finish(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_StorageList *stl = ((SCULPT_Data *)vedata)->stl;
+
+ /* Do something here! dependant on the objects gathered */
+ UNUSED_VARS(psl, stl);
+}
+
+/* Draw time ! Control rendering pipeline from here */
+static void SCULPT_draw_scene(void *vedata)
+{
+ SCULPT_PassList *psl = ((SCULPT_Data *)vedata)->psl;
+ SCULPT_FramebufferList *fbl = ((SCULPT_Data *)vedata)->fbl;
+
+ /* Default framebuffer and texture */
+ DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+
+ UNUSED_VARS(fbl, dfbl, dtxl);
+
+ /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
+ /*
+ * DRW_framebuffer_texture_detach(dtxl->depth);
+ * DRW_framebuffer_bind(fbl->custom_fb);
+ * DRW_draw_pass(psl->pass);
+ * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0);
+ * DRW_framebuffer_bind(dfbl->default_fb);
+ */
+
+ /* ... or just render passes on default framebuffer. */
+ DRW_draw_pass(psl->pass);
+
+ /* If you changed framebuffer, double check you rebind
+ * the default one with its textures attached before finishing */
+}
+
+/* Cleanup when destroying the engine.
+ * This is not per viewport ! only when quitting blender.
+ * Mostly used for freeing shaders */
+static void SCULPT_engine_free(void)
+{
+ // if (custom_shader)
+ // DRW_shader_free(custom_shader);
+}
+
+/* Create collection settings here.
+ *
+ * Be sure to add this function there :
+ * source/blender/draw/DRW_engine.h
+ * source/blender/blenkernel/intern/layer.c
+ * source/blenderplayer/bad_level_call_stubs/stubs.c
+ *
+ * And relevant collection settings to :
+ * source/blender/makesrna/intern/rna_scene.c
+ * source/blender/blenkernel/intern/layer.c
+ */
+#if 0
+void SCULPT_collection_settings_create(CollectionEngineSettings *ces)
+{
+ BLI_assert(ces);
+ // BKE_collection_engine_property_add_int(ces, "my_bool_prop", false);
+ // BKE_collection_engine_property_add_int(ces, "my_int_prop", 0);
+ // BKE_collection_engine_property_add_float(ces, "my_float_prop", 0.0f);
+}
+#endif
+
+DrawEngineType draw_engine_sculpt_type = {
+ NULL, NULL,
+ N_("SculptMode"),
+ &SCULPT_engine_init,
+ &SCULPT_engine_free,
+ &SCULPT_cache_init,
+ &SCULPT_cache_populate,
+ &SCULPT_cache_finish,
+ NULL, /* draw_background but not needed by mode engines */
+ &SCULPT_draw_scene
+};
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
new file mode 100644
index 00000000000..579a5f5089b
--- /dev/null
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -0,0 +1,55 @@
+
+/* keep in sync with GlobalsUboStorage */
+layout(std140) uniform globalsBlock {
+ vec4 colorWire;
+ vec4 colorWireEdit;
+ vec4 colorActive;
+ vec4 colorSelect;
+ vec4 colorTransform;
+ vec4 colorGroupActive;
+ vec4 colorGroup;
+ vec4 colorLamp;
+ vec4 colorSpeaker;
+ vec4 colorCamera;
+ vec4 colorEmpty;
+ vec4 colorVertex;
+ vec4 colorVertexSelect;
+ vec4 colorEditMeshActive;
+ vec4 colorEdgeSelect;
+ vec4 colorEdgeSeam;
+ vec4 colorEdgeSharp;
+ vec4 colorEdgeCrease;
+ vec4 colorEdgeBWeight;
+ vec4 colorEdgeFaceSelect;
+ vec4 colorFace;
+ vec4 colorFaceSelect;
+ vec4 colorNormal;
+ vec4 colorVNormal;
+ vec4 colorLNormal;
+ vec4 colorFaceDot;
+
+ vec4 colorDeselect;
+ vec4 colorOutline;
+ vec4 colorLampNoAlpha;
+
+ vec4 colorBackground;
+
+ vec4 colorGrid;
+ vec4 colorGridEmphasise;
+ vec4 colorGridAxisX;
+ vec4 colorGridAxisY;
+ vec4 colorGridAxisZ;
+
+ float sizeLampCenter;
+ float sizeLampCircle;
+ float sizeLampCircleShadow;
+ float sizeVertex;
+ float sizeEdge;
+ float sizeEdgeFix;
+ float sizeFaceDot;
+
+ float gridDistance;
+ float gridResolution;
+ float gridSubdivisions;
+ float gridScale;
+};
diff --git a/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl
new file mode 100644
index 00000000000..9c70eabc056
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_face_vert.glsl
@@ -0,0 +1,18 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float normalSize;
+
+in vec3 pos;
+in vec4 norAndFlag;
+
+flat out vec4 v1;
+flat out vec4 v2;
+
+void main()
+{
+ v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 n = normalize(NormalMatrix * norAndFlag.xyz); /* viewspace */
+ v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
+}
diff --git a/source/blender/draw/modes/shaders/edit_normals_geom.glsl b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
new file mode 100644
index 00000000000..d17823f2f5a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_geom.glsl
@@ -0,0 +1,15 @@
+
+layout(points) in;
+layout(line_strip, max_vertices=2) out;
+
+flat in vec4 v1[1];
+flat in vec4 v2[1];
+
+void main()
+{
+ gl_Position = v1[0];
+ EmitVertex();
+ gl_Position = v2[0];
+ EmitVertex();
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_normals_vert.glsl b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
new file mode 100644
index 00000000000..3e00181c8dd
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_normals_vert.glsl
@@ -0,0 +1,24 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+uniform mat4 ProjectionMatrix;
+uniform float normalSize;
+
+in vec3 pos;
+
+#ifdef FACE_NORMALS
+in vec4 norAndFlag;
+#define nor norAndFlag.xyz
+#else
+in vec3 nor;
+#endif
+
+flat out vec4 v1;
+flat out vec4 v2;
+
+void main()
+{
+ v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vec3 n = normalize(NormalMatrix * nor); /* viewspace */
+ v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl
new file mode 100644
index 00000000000..9b3fe6286e8
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_facedot_frag.glsl
@@ -0,0 +1,12 @@
+
+flat in int isSelected;
+
+out vec4 FragColor;
+
+void main()
+{
+ if (isSelected != 0)
+ FragColor = colorFaceDot;
+ else
+ FragColor = colorWireEdit;
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_facedot_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_facedot_vert.glsl
new file mode 100644
index 00000000000..2e541fa75e6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_facedot_vert.glsl
@@ -0,0 +1,14 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in vec4 norAndFlag;
+
+flat out int isSelected;
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ gl_PointSize = sizeFaceDot;
+ isSelected = int(norAndFlag.w);
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl
new file mode 100644
index 00000000000..fa0197573ff
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_facefill_frag.glsl
@@ -0,0 +1,27 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+flat in vec4 faceColor;
+flat in int faceActive;
+
+out vec4 FragColor;
+
+const mat4 stipple_matrix = mat4(vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0));
+
+void main()
+{
+ FragColor = faceColor;
+
+ if (faceActive == 1) {
+ int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */
+ int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */
+ FragColor *= stipple_matrix[x][y];
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl
new file mode 100644
index 00000000000..5755ba40951
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_facefill_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in ivec4 data;
+
+flat out vec4 faceColor;
+flat out int faceActive;
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ if ((data.x & FACE_ACTIVE) != 0) {
+ faceColor = colorEditMeshActive;
+ faceActive = 1;
+ }
+ else if ((data.x & FACE_SELECTED) != 0) {
+ faceColor = colorFaceSelect;
+ faceActive = 0;
+ }
+ else {
+ faceColor = colorFace;
+ faceActive = 0;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_frag.glsl
new file mode 100644
index 00000000000..cca1a2cc8e5
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_frag.glsl
@@ -0,0 +1,185 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform float faceAlphaMod;
+
+flat in vec3 edgesCrease;
+flat in vec3 edgesBweight;
+flat in ivec3 flag;
+flat in vec4 faceColor;
+flat in int clipCase;
+#ifdef VERTEX_SELECTION
+smooth in vec3 vertexColor;
+#endif
+
+/* We use a vec4[2] interface to pass edge data
+ * (without fragmenting memory accesses)
+ *
+ * There is 2 cases :
+ *
+ * - Simple case : geometry shader return edge distances
+ * in the first 2 components of the first vec4.
+ * This needs noperspective interpolation.
+ * The rest is filled with vertex screen positions.
+ * eData1.zw actually contain v2
+ * eData2.xy actually contain v1
+ * eData2.zw actually contain v0
+ *
+ * - Hard case : two 2d edge corner are described by each
+ * vec4 as origin and direction. This is constant over
+ * the triangle and use to detect the correct case. */
+
+noperspective in vec4 eData1;
+flat in vec4 eData2;
+
+out vec4 FragColor;
+
+#define EDGE_EXISTS (1 << 0)
+#define EDGE_ACTIVE (1 << 1)
+#define EDGE_SELECTED (1 << 2)
+#define EDGE_SEAM (1 << 3)
+#define EDGE_SHARP (1 << 4)
+/* Vertex flag is shifted and combined with the edge flag */
+#define VERTEX_ACTIVE (1 << (0 + 8))
+#define VERTEX_SELECTED (1 << (1 + 8))
+#define FACE_ACTIVE (1 << (2 + 8))
+
+/* Style Parameters in pixel */
+
+/* Array to retreive vert/edge indices */
+const ivec3 clipEdgeIdx[6] = ivec3[6](
+ ivec3(1, 0, 2),
+ ivec3(2, 0, 1),
+ ivec3(2, 1, 0),
+ ivec3(2, 1, 0),
+ ivec3(2, 0, 1),
+ ivec3(1, 0, 2)
+);
+
+const ivec3 clipPointIdx[6] = ivec3[6](
+ ivec3(0, 1, 2),
+ ivec3(0, 2, 1),
+ ivec3(0, 2, 1),
+ ivec3(1, 2, 0),
+ ivec3(1, 2, 0),
+ ivec3(2, 1, 0)
+);
+
+const mat4 stipple_matrix = mat4(vec4(1.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0),
+ vec4(0.0, 0.0, 1.0, 0.0),
+ vec4(0.0, 0.0, 0.0, 0.0));
+
+void colorDist(vec4 color, float dist)
+{
+ FragColor = (dist < 0) ? color : FragColor;
+}
+
+float distToEdge(vec2 o, vec2 dir)
+{
+ vec2 af = gl_FragCoord.xy - o;
+ float daf = dot(dir, af);
+ return sqrt(abs(dot(af, af) - daf * daf));
+}
+
+void main()
+{
+ vec3 e, p;
+
+ /* Step 1 : Computing Distances */
+
+ if (clipCase == 0) {
+ e.xy = eData1.xy;
+
+ /* computing missing distance */
+ vec2 dir = normalize(eData2.zw - eData2.xy);
+ e.z = distToEdge(eData2.zw, dir);
+
+ p.x = distance(eData2.zw, gl_FragCoord.xy);
+ p.y = distance(eData2.xy, gl_FragCoord.xy);
+ p.z = distance(eData1.zw, gl_FragCoord.xy);
+ }
+ else {
+ ivec3 eidxs = clipEdgeIdx[clipCase - 1];
+ ivec3 pidxs = clipPointIdx[clipCase - 1];
+
+ e[eidxs.x] = distToEdge(eData1.xy, eData1.zw);
+ e[eidxs.y] = distToEdge(eData2.xy, eData2.zw);
+
+ /* Three edges visible cases */
+ if (clipCase == 1 || clipCase == 2 || clipCase == 4) {
+ e[eidxs.z] = distToEdge(eData1.xy, normalize(eData2.xy - eData1.xy));
+ p[pidxs.y] = distance(eData2.xy, gl_FragCoord.xy);
+ }
+ else {
+ e[eidxs.z] = 1e10; /* off screen */
+ p[pidxs.y] = 1e10; /* off screen */
+ }
+
+ p[pidxs.x] = distance(eData1.xy, gl_FragCoord.xy);
+ p[pidxs.z] = 1e10; /* off screen */
+ }
+
+ /* Step 2 : coloring (order dependant) */
+
+ /* First */
+ FragColor = faceColor;
+
+ if ((flag[0] & FACE_ACTIVE) != 0) {
+ int x = int(gl_FragCoord.x) & 0x3; /* mod 4 */
+ int y = int(gl_FragCoord.y) & 0x3; /* mod 4 */
+ FragColor *= stipple_matrix[x][y];
+ }
+ else {
+ FragColor.a *= faceAlphaMod;
+ }
+
+ /* Edges */
+ for (int v = 0; v < 3; ++v) {
+ if ((flag[v] & EDGE_EXISTS) != 0) {
+ float largeEdge = e[v] - sizeEdge * 2.0;
+ float innerEdge = e[v] - sizeEdge;
+
+ if ((flag[v] & EDGE_SEAM) != 0)
+ colorDist(colorEdgeSeam, largeEdge);
+ else if (edgesBweight[v] > 0.0)
+ colorDist(vec4(colorEdgeBWeight.rgb, edgesBweight[v]), largeEdge);
+ else if (edgesCrease[v] > 0.0)
+ colorDist(vec4(colorEdgeCrease.rgb, edgesCrease[v]), largeEdge);
+ else if ((flag[v] & EDGE_SHARP) != 0)
+ colorDist(colorEdgeSharp, largeEdge);
+#ifndef VERTEX_SELECTION
+ else
+ colorDist(colorWireEdit, innerEdge);
+
+ if ((flag[v] & EDGE_ACTIVE) != 0)
+ colorDist(vec4(colorEditMeshActive.xyz, 1.0), innerEdge);
+ else if ((flag[v] & EDGE_SELECTED) != 0)
+ colorDist(colorEdgeSelect, innerEdge);
+#else
+ colorDist(vec4(vertexColor, 1.0), innerEdge);
+#endif
+ }
+ }
+
+ /* Points */
+#ifdef VERTEX_SELECTION
+ for (int v = 0; v < 3; ++v) {
+ float size = p[v] - sizeVertex;
+
+ if ((flag[v] & VERTEX_ACTIVE) != 0)
+ colorDist(vec4(colorEditMeshActive.xyz, 1.0), size);
+ else if ((flag[v] & VERTEX_SELECTED) != 0)
+ colorDist(colorVertexSelect, size);
+ else
+ colorDist(colorVertex, size);
+ }
+#endif
+
+ /* don't write depth if not opaque */
+ if (FragColor.a == 0.0) discard;
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_geom_edge.glsl b/source/blender/draw/modes/shaders/edit_overlay_geom_edge.glsl
new file mode 100644
index 00000000000..ddeecf12bd6
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_geom_edge.glsl
@@ -0,0 +1,143 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+layout(lines) in;
+layout(triangle_strip, max_vertices=6) out;
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec4 vPos[];
+in vec4 pPos[];
+in ivec4 vData[];
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesSharp;
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+#ifdef VERTEX_SELECTION
+smooth out vec3 vertexColor;
+#endif
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+/* Table 1. Triangle Projection Cases */
+const ivec4 clipPointsIdx[6] = ivec4[6](
+ ivec4(0, 1, 2, 2),
+ ivec4(0, 2, 1, 1),
+ ivec4(0, 0, 1, 2),
+ ivec4(1, 2, 0, 0),
+ ivec4(1, 1, 0, 2),
+ ivec4(2, 2, 0, 1)
+);
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], vec2 vpos, int v)
+{
+ /* endpoints of opposite edge */
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+ /* Edge normalized vector */
+ vec2 dir = normalize(e2 - e1);
+ /* perpendicular to dir */
+ vec2 orthogonal = vec2(-dir.y, dir.x);
+
+ return abs(dot(vpos - e1, orthogonal));
+}
+
+vec3 getVertexColor(int v)
+{
+ if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0)
+ return colorEdgeSelect.rgb;
+ else
+ return colorWireEdit.rgb;
+}
+
+void doVertex(int v, vec4 pos)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = getVertexColor(v);
+#endif
+
+ gl_Position = pos;
+
+ EmitVertex();
+}
+
+void main()
+{
+ clipCase = 0;
+
+ /* Face */
+ faceColor = vec4(0.0);
+
+ /* Proj Vertex */
+ vec2 pos[2] = vec2[2](proj(pPos[0]), proj(pPos[1]));
+
+ /* little optimization use a vec4 to vectorize
+ * following operations */
+ vec4 dirs1, dirs2;
+
+ /* Edge normalized vector */
+ dirs1.xy = normalize(pos[1] - pos[0]);
+
+ /* perpendicular to dir */
+ dirs1.zw = vec2(-dirs1.y, dirs1.x);
+
+ /* Make it view independant */
+ dirs1 *= sizeEdgeFix / viewportSize.xyxy;
+
+ dirs2 = dirs1;
+
+ /* Perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* vPos[i].z is negative and we don't want
+ * our fixvec to be flipped */
+ dirs1 *= -vPos[0].z;
+ dirs2 *= -vPos[1].z;
+ }
+
+ /* Edge / Vert data */
+ eData1 = vec4(1e10);
+ eData2.zw = pos[0];
+ eData2.xy = pos[1];
+ flag[0] = (vData[0].x << 8);
+ flag[1] = (vData[1].x << 8);
+ flag[2] = 0;
+
+ doVertex(0, pPos[0] + vec4(-dirs1.xy, 0.0, 0.0));
+ doVertex(0, pPos[0] + vec4( dirs1.zw, 0.0, 0.0));
+ doVertex(0, pPos[0] + vec4(-dirs1.zw, 0.0, 0.0));
+
+ flag[2] = vData[0].y | (vData[0].x << 8);
+ edgesCrease[2] = vData[0].z / 255.0;
+ edgesSharp[2] = vData[0].w / 255.0;
+
+ doVertex(1, pPos[1] + vec4( dirs2.zw, 0.0, 0.0));
+ doVertex(1, pPos[1] + vec4(-dirs2.zw, 0.0, 0.0));
+
+ flag[2] = 0;
+ doVertex(1, pPos[1] + vec4( dirs2.xy, 0.0, 0.0));
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_geom_tri.glsl b/source/blender/draw/modes/shaders/edit_overlay_geom_tri.glsl
new file mode 100644
index 00000000000..41aade3d3c7
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_geom_tri.glsl
@@ -0,0 +1,277 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+layout(triangles) in;
+
+#ifdef EDGE_FIX
+/* To fix the edge artifacts, we render
+ * an outline strip around the screenspace
+ * triangle. Order is important.
+ * TODO diagram
+ */
+
+#ifdef VERTEX_SELECTION
+layout(triangle_strip, max_vertices=23) out;
+#else
+layout(triangle_strip, max_vertices=17) out;
+#endif
+#else
+layout(triangle_strip, max_vertices=3) out;
+#endif
+
+uniform mat4 ProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec4 vPos[];
+in vec4 pPos[];
+in ivec4 vData[];
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out vec3 edgesCrease;
+flat out vec3 edgesSharp;
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+#ifdef VERTEX_SELECTION
+smooth out vec3 vertexColor;
+#endif
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+
+#define VERTEX_ACTIVE (1 << 0)
+#define VERTEX_SELECTED (1 << 1)
+
+#define FACE_ACTIVE (1 << 2)
+#define FACE_SELECTED (1 << 3)
+
+/* Table 1. Triangle Projection Cases */
+const ivec4 clipPointsIdx[6] = ivec4[6](
+ ivec4(0, 1, 2, 2),
+ ivec4(0, 2, 1, 1),
+ ivec4(0, 0, 1, 2),
+ ivec4(1, 2, 0, 0),
+ ivec4(1, 1, 0, 2),
+ ivec4(2, 2, 0, 1)
+);
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+float dist(vec2 pos[3], vec2 vpos, int v)
+{
+ /* endpoints of opposite edge */
+ vec2 e1 = pos[(v + 1) % 3];
+ vec2 e2 = pos[(v + 2) % 3];
+ /* Edge normalized vector */
+ vec2 dir = normalize(e2 - e1);
+ /* perpendicular to dir */
+ vec2 orthogonal = vec2(-dir.y, dir.x);
+
+ return abs(dot(vpos - e1, orthogonal));
+}
+
+vec3 getVertexColor(int v)
+{
+ if ((vData[v].x & (VERTEX_ACTIVE | VERTEX_SELECTED)) != 0)
+ return colorEdgeSelect.rgb;
+ else
+ return colorWireEdit.rgb;
+}
+
+vec4 getClipData(vec2 pos[3], ivec2 vidx)
+{
+ vec2 A = pos[vidx.x];
+ vec2 Adir = normalize(A - pos[vidx.y]);
+
+ return vec4(A, Adir);
+}
+
+void doVertex(int v, vec4 pos)
+{
+#ifdef VERTEX_SELECTION
+ vertexColor = getVertexColor(v);
+#endif
+
+ gl_Position = pos;
+
+ EmitVertex();
+}
+
+void main()
+{
+ /* First we detect which case we are in */
+ clipCase = 0;
+
+ /* if perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* See Table 1. Triangle Projection Cases */
+ clipCase += int(pPos[0].z / pPos[0].w < -1 || vPos[0].z > 0.0) * 4;
+ clipCase += int(pPos[1].z / pPos[1].w < -1 || vPos[1].z > 0.0) * 2;
+ clipCase += int(pPos[2].z / pPos[2].w < -1 || vPos[2].z > 0.0) * 1;
+ }
+
+ /* If triangle is behind nearplane, early out */
+ if (clipCase == 7)
+ return;
+
+ /* Edge */
+ ivec3 eflag; vec3 ecrease, esharp;
+ for (int v = 0; v < 3; ++v) {
+ flag[v] = eflag[v] = vData[v].y | (vData[v].x << 8);
+ edgesCrease[v] = ecrease[v] = vData[v].z / 255.0;
+ edgesSharp[v] = esharp[v] = vData[v].w / 255.0;
+ }
+
+ /* Face */
+ if ((vData[0].x & FACE_ACTIVE) != 0)
+ faceColor = colorEditMeshActive;
+ else if ((vData[0].x & FACE_SELECTED) != 0)
+ faceColor = colorFaceSelect;
+ else
+ faceColor = colorFace;
+
+ /* Vertex */
+ vec2 pos[3] = vec2[3](proj(pPos[0]), proj(pPos[1]), proj(pPos[2]));
+
+ /* Simple case : compute edge distances in geometry shader */
+ if (clipCase == 0) {
+
+ /* Packing screen positions and 2 distances */
+ eData1 = vec4(0.0, 0.0, pos[2]);
+ eData2 = vec4(pos[1], pos[0]);
+
+ /* Only pass the first 2 distances */
+ for (int v = 0; v < 2; ++v) {
+ eData1[v] = dist(pos, pos[v], v);
+ doVertex(v, pPos[v]);
+ eData1[v] = 0.0;
+ }
+
+ /* and the last vertex */
+ doVertex(2, pPos[2]);
+
+#ifdef EDGE_FIX
+ vec2 fixvec[6];
+ vec2 fixvecaf[6];
+ vec2 cornervec[3];
+
+ /* This fix the case when 2 vertices are perfectly aligned
+ * and corner vectors have nowhere to go.
+ * ie: length(cornervec[i]) == 0 */
+ const float epsilon = 1e-2; /* in pixel so not that much */
+ const vec2 bias[3] = vec2[3](
+ vec2( epsilon, epsilon),
+ vec2(-epsilon, epsilon),
+ vec2( 0.0, -epsilon)
+ );
+
+ for (int i = 0; i < 3; ++i) {
+ int i1 = (i + 1) % 3;
+ int i2 = (i + 2) % 3;
+
+ vec2 v1 = pos[i] + bias[i];
+ vec2 v2 = pos[i1] + bias[i1];
+ vec2 v3 = pos[i2] + bias[i2];
+
+ /* Edge normalized vector */
+ vec2 dir = normalize(v2 - v1);
+ vec2 dir2 = normalize(v3 - v1);
+
+ cornervec[i] = -normalize(dir + dir2);
+
+ /* perpendicular to dir */
+ vec2 perp = vec2(-dir.y, dir.x);
+
+ /* Backface case */
+ if (dot(perp, dir2) > 0) {
+ perp = -perp;
+ }
+
+ /* Make it view independant */
+ perp *= sizeEdgeFix / viewportSize;
+ cornervec[i] *= sizeEdgeFix / viewportSize;
+ fixvec[i] = fixvecaf[i] = perp;
+
+ /* Perspective */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ /* vPos[i].z is negative and we don't want
+ * our fixvec to be flipped */
+ fixvec[i] *= -vPos[i].z;
+ fixvecaf[i] *= -vPos[i1].z;
+ cornervec[i] *= -vPos[i].z;
+ }
+ }
+
+ /* to not let face color bleed */
+ faceColor = vec4(0.0, 0.0, 0.0, 0.0);
+
+ /* we don't want other edges : make them far*/
+ eData1 = vec4(1e10);
+
+ /* Start with the same last vertex to create a
+ * degenerate triangle in order to "create"
+ * a new triangle strip */
+ for (int i = 2; i < 5; ++i) {
+ int vbe = (i - 1) % 3;
+ int vaf = (i + 1) % 3;
+ int v = i % 3;
+
+ /* Position of the "hidden" thrid vertex */
+ eData1.zw = pos[vbe];
+
+ doVertex(v, pPos[v]);
+ doVertex(v, pPos[v] + vec4(fixvec[v], 0.0, 0.0));
+
+ /* Now one triangle only shade one edge
+ * so we use the edge distance calculated
+ * in the fragment shader, the third edge;
+ * we do this because we need flat interp to
+ * draw a continuous triangle strip */
+ eData2.xy = pos[vaf];
+ eData2.zw = pos[v];
+ flag[0] = (vData[v].x << 8);
+ flag[1] = (vData[vaf].x << 8);
+ flag[2] = eflag[vbe];
+ edgesCrease[2] = ecrease[vbe];
+ edgesSharp[2] = esharp[vbe];
+
+ doVertex(vaf, pPos[vaf]);
+ doVertex(vaf, pPos[vaf] + vec4(fixvecaf[v], 0.0, 0.0));
+
+ /* corner vertices should not drax edges but draw point only */
+ flag[2] = (vData[vbe].x << 8);
+#ifdef VERTEX_SELECTION
+ doVertex(vaf, pPos[vaf]);
+ doVertex(vaf, pPos[vaf] + vec4(cornervec[vaf], 0.0, 0.0));
+#endif
+ }
+
+ /* finish the loop strip */
+ doVertex(2, pPos[2]);
+ doVertex(2, pPos[2] + vec4(fixvec[2], 0.0, 0.0));
+#endif
+ }
+ /* Harder case : compute visible edges vectors */
+ else {
+ ivec4 vindices = clipPointsIdx[clipCase - 1];
+
+ eData1 = getClipData(pos, vindices.xz);
+ eData2 = getClipData(pos, vindices.yw);
+
+ for (int v = 0; v < 3; ++v)
+ doVertex(v, pPos[v]);
+ }
+
+ EndPrimitive();
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_loosevert_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_loosevert_vert.glsl
new file mode 100644
index 00000000000..3ff76a77da2
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_loosevert_vert.glsl
@@ -0,0 +1,48 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform mat4 ModelViewProjectionMatrix;
+uniform vec2 viewportSize;
+
+in vec3 pos;
+in ivec4 data;
+
+/* these are the same for all vertices
+ * and does not need interpolation */
+flat out ivec3 flag;
+flat out vec4 faceColor;
+flat out int clipCase;
+
+/* See fragment shader */
+noperspective out vec4 eData1;
+flat out vec4 eData2;
+
+/* project to screen space */
+vec2 proj(vec4 pos)
+{
+ return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize;
+}
+
+void main()
+{
+ clipCase = 0;
+
+ vec4 pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+
+ /* there is no face */
+ faceColor = vec4(0.0);
+
+ /* only verterx position 0 is used */
+ eData1 = eData2 = vec4(1e10);
+ eData2.zw = proj(pPos);
+
+ flag = ivec3(0);
+ flag[0] = (data.x << 8);
+
+ gl_PointSize = sizeEdgeFix;
+ gl_Position = pPos;
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl b/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl
new file mode 100644
index 00000000000..f567a3a5cbd
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_mix_frag.glsl
@@ -0,0 +1,24 @@
+
+out vec4 FragColor;
+
+uniform sampler2D wireColor;
+uniform sampler2D wireDepth;
+uniform sampler2D sceneDepth;
+uniform float alpha;
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ float wire_depth = texelFetch(wireDepth, uv, 0).r;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ vec4 wire_color = texelFetch(wireColor, uv, 0).rgba;
+
+ FragColor = wire_color;
+
+ /* this works because not rendered depth is 1.0 and the
+ * following test is always true even when no wires */
+ if ((wire_depth > scene_depth) && (wire_color.a > 0)) {
+ /* Note : Using wire_color.a * alpha produce unwanted result */
+ FragColor.a = alpha;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/edit_overlay_vert.glsl b/source/blender/draw/modes/shaders/edit_overlay_vert.glsl
new file mode 100644
index 00000000000..5bc9a8bef85
--- /dev/null
+++ b/source/blender/draw/modes/shaders/edit_overlay_vert.glsl
@@ -0,0 +1,23 @@
+
+/* Solid Wirefram implementation
+ * Mike Erwin, Clément Foucault */
+
+/* This shader follows the principles of
+ * http://developer.download.nvidia.com/SDK/10/direct3d/Source/SolidWireframe/Doc/SolidWireframe.pdf */
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ModelViewProjectionMatrix;
+
+in vec3 pos;
+in ivec4 data;
+
+out vec4 vPos;
+out vec4 pPos;
+out ivec4 vData;
+
+void main()
+{
+ vPos = ModelViewMatrix * vec4(pos, 1.0);
+ pPos = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ vData = data;
+}
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
new file mode 100644
index 00000000000..9b1283e46af
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -0,0 +1,147 @@
+
+/* Infinite grid
+ * Clément Foucault */
+
+in vec3 wPos;
+
+out vec4 FragColor;
+
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec3 eye;
+uniform vec4 gridSettings;
+uniform float gridOneOverLogSubdiv;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define AXIS_X (1 << 0)
+#define AXIS_Y (1 << 1)
+#define AXIS_Z (1 << 2)
+#define GRID (1 << 3)
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+
+#define GRID_LINE_SMOOTH 1.15
+
+float grid(vec3 uv, vec3 fwidthCos, float grid_size)
+{
+ float half_size = grid_size / 2.0;
+ /* triangular wave pattern, amplitude is [0, grid_size] */
+ vec3 grid_domain = abs(mod(uv + half_size, grid_size) - half_size);
+ /* modulate by the absolute rate of change of the uvs
+ * (make lines have the same width under perspective) */
+ grid_domain /= fwidthCos;
+
+ /* collapse waves and normalize */
+ grid_domain.x = min(grid_domain.x, min(grid_domain.y, grid_domain.z)) / grid_size;
+
+ return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH / grid_size, grid_domain.x);
+}
+
+float axis(float u, float fwidthU, float line_size)
+{
+ float axis_domain = abs(u);
+ /* modulate by the absolute rate of change of the uvs
+ * (make line have the same width under perspective) */
+ axis_domain /= fwidthU;
+
+ return 1.0 - smoothstep(0.0, GRID_LINE_SMOOTH, axis_domain - line_size);
+}
+
+void main()
+{
+ vec3 fwidthCos = fwidth(wPos);
+
+ float dist, fade;
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vec3 viewvec = cameraPos - wPos;
+ dist = length(viewvec);
+ viewvec /= dist;
+
+ float angle;
+ if ((gridFlag & PLANE_XZ) > 0)
+ angle = viewvec.y;
+ else if ((gridFlag & PLANE_YZ) > 0)
+ angle = viewvec.x;
+ else
+ angle = viewvec.z;
+
+ angle = 1.0 - abs(angle);
+ fade = 1.0 - angle * angle;
+ fade *= 1.0 - smoothstep(0.0, gridDistance, dist - gridDistance);
+ }
+ else {
+ dist = abs(gl_FragCoord.z * 2.0 - 1.0);
+ fade = 1.0 - smoothstep(0.0, 0.5, dist - 0.5);
+ dist = 1.0; /* avoid branch after */
+
+ if ((gridFlag & PLANE_XY) > 0) {
+ float angle = 1.0 - abs(eye.z);
+ fade *= 1.0 - angle * angle * angle;
+ dist = 1.0 + angle * 2.0;
+ }
+ }
+
+ if ((gridFlag & GRID) > 0) {
+ float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
+
+ float blend = fract(-max(grid_res, 0.0));
+ float lvl = floor(grid_res);
+
+ /* from smallest to biggest */
+ float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
+ float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
+ float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
+
+ float gridA = grid(wPos, fwidthCos, scaleA);
+ float gridB = grid(wPos, fwidthCos, scaleB);
+ float gridC = grid(wPos, fwidthCos, scaleC);
+
+ FragColor = vec4(colorGrid.rgb, gridA * blend);
+ FragColor = mix(FragColor, vec4(mix(colorGrid.rgb, colorGridEmphasise.rgb, blend), 1.0), gridB);
+ FragColor = mix(FragColor, vec4(colorGridEmphasise.rgb, 1.0), gridC);
+ }
+ else {
+ FragColor = vec4(colorGrid.rgb, 0.0);
+ }
+
+ if ((gridFlag & AXIS_X) > 0) {
+ float xAxis;
+ if ((gridFlag & PLANE_XZ) > 0) {
+ xAxis = axis(wPos.z, fwidthCos.z, 0.1);
+ }
+ else {
+ xAxis = axis(wPos.y, fwidthCos.y, 0.1);
+ }
+ FragColor = mix(FragColor, colorGridAxisX, xAxis);
+ }
+ if ((gridFlag & AXIS_Y) > 0) {
+ float yAxis;
+ if ((gridFlag & PLANE_YZ) > 0) {
+ yAxis = axis(wPos.z, fwidthCos.z, 0.1);
+ }
+ else {
+ yAxis = axis(wPos.x, fwidthCos.x, 0.1);
+ }
+ FragColor = mix(FragColor, colorGridAxisY, yAxis);
+ }
+ if ((gridFlag & AXIS_Z) > 0) {
+ float zAxis;
+ if ((gridFlag & PLANE_YZ) > 0) {
+ zAxis = axis(wPos.y, fwidthCos.y, 0.1);
+ }
+ else {
+ zAxis = axis(wPos.x, fwidthCos.x, 0.1);
+ }
+ FragColor = mix(FragColor, colorGridAxisZ, zAxis);
+ }
+
+ FragColor.a *= fade;
+} \ No newline at end of file
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
new file mode 100644
index 00000000000..2da8e45c560
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -0,0 +1,66 @@
+
+/* Infinite grid
+ * Clément Foucault */
+
+uniform mat4 ViewProjectionOffsetMatrix;
+uniform mat4 ProjectionMatrix;
+uniform vec3 cameraPos;
+uniform vec4 gridSettings;
+
+#define gridDistance gridSettings.x
+#define gridResolution gridSettings.y
+#define gridScale gridSettings.z
+#define gridSubdiv gridSettings.w
+
+uniform int gridFlag;
+
+#define PLANE_XY (1 << 4)
+#define PLANE_XZ (1 << 5)
+#define PLANE_YZ (1 << 6)
+#define CLIP_Z_POS (1 << 7)
+#define CLIP_Z_NEG (1 << 8)
+
+in vec3 pos;
+
+out vec3 wPos;
+
+void main()
+{
+ vec3 vert_pos, proj_camera_pos;
+
+ /* Project camera pos to the needed plane */
+ if ((gridFlag & PLANE_XY) > 0) {
+ vert_pos = vec3(pos.x, pos.y, 0.0);
+ proj_camera_pos = vec3(cameraPos.x, cameraPos.y, 0.0);
+ }
+ else if ((gridFlag & PLANE_XZ) > 0) {
+ vert_pos = vec3(pos.x, 0.0, pos.y);
+ proj_camera_pos = vec3(cameraPos.x, 0.0, cameraPos.z);
+ }
+ else {
+ vert_pos = vec3(0.0, pos.x, pos.y);
+ proj_camera_pos = vec3(0.0, cameraPos.y, cameraPos.z);
+ }
+
+ /* if persp */
+ if (ProjectionMatrix[3][3] == 0.0) {
+ vert_pos *= gridDistance * 2.0;
+ }
+ else {
+ float viewdist = 1.0f / min(abs(ProjectionMatrix[0][0]), abs(ProjectionMatrix[1][1]));
+ vert_pos *= viewdist * gridDistance * 2.0;
+ }
+
+ vec3 realPos = proj_camera_pos + vert_pos;
+
+ /* Used for additional Z axis */
+ if ((gridFlag & CLIP_Z_POS) > 0) {
+ realPos.z = max(realPos.z, 0.0);
+ }
+ if ((gridFlag & CLIP_Z_NEG) > 0) {
+ realPos.z = min(realPos.z, 0.0);
+ }
+
+ gl_Position = ViewProjectionOffsetMatrix * vec4(realPos, 1.0);
+ wPos = realPos;
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
new file mode 100644
index 00000000000..5565a0f1e09
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_detect_frag.glsl
@@ -0,0 +1,61 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineColor;
+uniform sampler2D outlineDepth;
+uniform sampler2D sceneDepth;
+
+uniform float alphaOcclu;
+uniform vec2 viewportSize;
+
+void search_outline(ivec2 uv, vec4 ref_col, inout bool ref_occlu, inout bool outline)
+{
+ if (!outline) {
+ vec4 color = texelFetch(outlineColor, uv, 0).rgba;
+ if (color != ref_col) {
+ outline = true;
+ }
+ else {
+ float depth = texelFetch(outlineDepth, uv, 0).r;
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+ bool occlu = (depth > scene_depth);
+
+ if (occlu != ref_occlu && !ref_occlu) {
+ outline = true;
+ }
+ }
+ }
+}
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ vec4 ref_col = texelFetch(outlineColor, uv, 0).rgba;
+
+ float depth = texelFetch(outlineDepth, uv, 0).r;
+ /* Modulate color if occluded */
+ float scene_depth = texelFetch(sceneDepth, uv, 0).r;
+
+ bool ref_occlu = (depth > scene_depth);
+
+ bool outline = false;
+
+ search_outline(uv + ivec2( 1, 0), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2( 0, 1), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2(-1, 0), ref_col, ref_occlu, outline);
+ search_outline(uv + ivec2( 0, -1), ref_col, ref_occlu, outline);
+
+ FragColor = ref_col;
+
+ /* We Hit something ! */
+ if (outline) {
+ if (ref_occlu) {
+ FragColor.a *= alphaOcclu;
+ }
+ }
+ else {
+ FragColor.a = 0.0;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
new file mode 100644
index 00000000000..e0568d1157a
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_expand_frag.glsl
@@ -0,0 +1,45 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineColor;
+uniform sampler2D outlineDepth;
+
+uniform float alpha;
+uniform bool doExpand;
+
+void search_outline(ivec2 uv, inout bool found_edge)
+{
+ if (!found_edge) {
+ vec4 color = texelFetch(outlineColor, uv, 0).rgba;
+ if (color.a != 0.0) {
+ if (doExpand || color.a != 1.0) {
+ FragColor = color;
+ found_edge = true;
+ }
+ }
+ }
+}
+
+void main()
+{
+ ivec2 uv = ivec2(gl_FragCoord.xy);
+ FragColor = texelFetch(outlineColor, uv, 0).rgba;
+ float depth = texelFetch(outlineDepth, uv, 0).r;
+
+ if (FragColor.a != 0.0 || (depth == 1.0 && !doExpand))
+ return;
+
+ bool found_edge = false;
+ search_outline(uv + ivec2( 1, 0), found_edge);
+ search_outline(uv + ivec2( 0, 1), found_edge);
+ search_outline(uv + ivec2(-1, 0), found_edge);
+ search_outline(uv + ivec2( 0, -1), found_edge);
+
+ /* We Hit something ! */
+ if (found_edge) {
+ /* only change alpha */
+ FragColor.a *= alpha;
+ }
+}
diff --git a/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
new file mode 100644
index 00000000000..3937828eca2
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_outline_resolve_frag.glsl
@@ -0,0 +1,11 @@
+
+in vec4 uvcoordsvar;
+
+out vec4 FragColor;
+
+uniform sampler2D outlineBluredColor;
+
+void main()
+{
+ FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba;
+}
diff --git a/source/blender/editors/CMakeLists.txt b/source/blender/editors/CMakeLists.txt
index 7e804a5bbfc..1559512d713 100644
--- a/source/blender/editors/CMakeLists.txt
+++ b/source/blender/editors/CMakeLists.txt
@@ -47,7 +47,6 @@ if(WITH_BLENDER)
add_subdirectory(space_graph)
add_subdirectory(space_image)
add_subdirectory(space_info)
- add_subdirectory(space_collections)
add_subdirectory(space_logic)
add_subdirectory(space_nla)
add_subdirectory(space_node)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index f41c4741eff..166889037ef 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -2781,7 +2781,7 @@ static bAnimChannelType ACF_DSMCLIP =
acf_generic_indention_1, /* indent level */
acf_generic_basic_offset, /* offset */
- acf_generic_idblock_name , /* name */
+ acf_generic_idblock_name, /* name */
acf_generic_idfill_name_prop, /* name prop */
acf_dsmclip_icon, /* icon */
@@ -3858,7 +3858,8 @@ void ANIM_channel_draw(bAnimContext *ac, bAnimListElem *ale, float yminc, float
if (ac->sl) {
if ((ac->spacetype == SPACE_IPO) &&
(acf->has_setting(ac, ale, ACHANNEL_SETTING_VISIBLE) ||
- acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE))) {
+ acf->has_setting(ac, ale, ACHANNEL_SETTING_ALWAYS_VISIBLE)))
+ {
/* for F-Curves, draw color-preview of curve behind checkbox */
if (ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_NLACURVE)) {
FCurve *fcu = (FCurve *)ale->data;
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 2b830657923..5d357e2f93e 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -46,6 +46,8 @@
#include "BLI_dlrbTree.h"
#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
#include "BKE_mask.h"
@@ -56,13 +58,12 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
/* *************************************************** */
/* CURRENT FRAME DRAWING */
@@ -79,8 +80,9 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
int slen;
/* because the frame number text is subject to the same scaling as the contents of the view */
+ gpuPushMatrix();
UI_view2d_scale_get(v2d, &xscale, &yscale);
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ gpuScale2f(1.0f / xscale, 1.0f);
/* get timecode string
* - padding on str-buf passed so that it doesn't sit on the frame indicator
@@ -113,7 +115,7 @@ static void draw_cfra_number(Scene *scene, View2D *v2d, const float cfra, const
UI_fontstyle_draw_simple(fstyle, x - 0.25f * U.widget_unit, y + 0.15f * U.widget_unit, numstr, col);
/* restore view transform */
- glScalef(xscale, 1.0, 1.0);
+ gpuPopMatrix();
}
/* General call for drawing current frame indicator in animation editor */
@@ -121,7 +123,8 @@ void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
{
Scene *scene = CTX_data_scene(C);
- const float x = (float)(scene->r.cfra * scene->r.framelen);
+ const float time = scene->r.cfra + scene->r.subframe;
+ const float x = (float)(time * scene->r.framelen);
glLineWidth((flag & DRAWCFRA_WIDE) ? 3.0 : 2.0);
@@ -330,7 +333,8 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo
fcu->prev_norm_factor = 1.0f;
if (fcu->bezt) {
- BezTriple *bezt;
+ const bool use_preview_only = PRVRANGEON;
+ const BezTriple *bezt;
int i;
float max_coord = -FLT_MAX;
float min_coord = FLT_MAX;
@@ -340,28 +344,77 @@ static float normalization_factor_get(Scene *scene, FCurve *fcu, short flag, flo
return 1.0f;
}
- if (PRVRANGEON) {
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- if (IN_RANGE_INCL(bezt->vec[1][0], scene->r.psfra, scene->r.pefra)) {
- max_coord = max_ff(max_coord, bezt->vec[0][1]);
- max_coord = max_ff(max_coord, bezt->vec[1][1]);
- max_coord = max_ff(max_coord, bezt->vec[2][1]);
-
- min_coord = min_ff(min_coord, bezt->vec[0][1]);
- min_coord = min_ff(min_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[2][1]);
- }
+ for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
+ if (use_preview_only && !IN_RANGE_INCL(bezt->vec[1][0],
+ scene->r.psfra,
+ scene->r.pefra))
+ {
+ continue;
}
- }
- else {
- for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, bezt++) {
- max_coord = max_ff(max_coord, bezt->vec[0][1]);
+
+ if (i == 0) {
+ /* We ignore extrapolation flags and handle here, and use the
+ * control point position only. so we normalize "interesting"
+ * part of the curve.
+ *
+ * Here we handle left extrapolation.
+ */
max_coord = max_ff(max_coord, bezt->vec[1][1]);
- max_coord = max_ff(max_coord, bezt->vec[2][1]);
- min_coord = min_ff(min_coord, bezt->vec[0][1]);
min_coord = min_ff(min_coord, bezt->vec[1][1]);
- min_coord = min_ff(min_coord, bezt->vec[2][1]);
+ }
+ else {
+ const BezTriple *prev_bezt = bezt - 1;
+ if (prev_bezt->ipo == BEZT_IPO_CONST) {
+ /* Constant interpolation: previous CV value is used up
+ * to the current keyframe.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_LIN) {
+ /* Linear interpolation: min/max using both previous and
+ * and current CV.
+ */
+ max_coord = max_ff(max_coord, bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, bezt->vec[1][1]);
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else if (prev_bezt->ipo == BEZT_IPO_BEZ) {
+ const int resol = fcu->driver
+ ? 32
+ : min_ii((int)(5.0f * len_v2v2(bezt->vec[1], prev_bezt->vec[1])), 32);
+ if (resol < 2) {
+ max_coord = max_ff(max_coord, prev_bezt->vec[1][1]);
+ min_coord = min_ff(min_coord, prev_bezt->vec[1][1]);
+ }
+ else {
+ float data[120];
+ float v1[2], v2[2], v3[2], v4[2];
+
+ v1[0] = prev_bezt->vec[1][0];
+ v1[1] = prev_bezt->vec[1][1];
+ v2[0] = prev_bezt->vec[2][0];
+ v2[1] = prev_bezt->vec[2][1];
+
+ v3[0] = bezt->vec[0][0];
+ v3[1] = bezt->vec[0][1];
+ v4[0] = bezt->vec[1][0];
+ v4[1] = bezt->vec[1][1];
+
+ correct_bezpart(v1, v2, v3, v4);
+
+ BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
+ BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
+
+ for (int j = 0; j <= resol; ++j) {
+ const float *fp = &data[j * 3];
+ max_coord = max_ff(max_coord, fp[1]);
+ min_coord = min_ff(min_coord, fp[1]);
+ }
+ }
+ }
}
}
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 7b6d30469a4..5b7ae216c55 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -74,6 +74,7 @@
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
#include "DNA_userdef_types.h"
+#include "DNA_layer_types.h"
#include "MEM_guardedalloc.h"
@@ -90,6 +91,7 @@
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_key.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_modifier.h"
@@ -130,11 +132,11 @@ static void animedit_get_yscale_factor(bAnimContext *ac)
/* Note: there's a similar function in key.c (BKE_key_from_object) */
static Key *actedit_get_shapekeys(bAnimContext *ac)
{
- Scene *scene = ac->scene;
+ SceneLayer *sl = ac->scene_layer;
Object *ob;
Key *key;
- ob = OBACT;
+ ob = OBACT_NEW;
if (ob == NULL)
return NULL;
@@ -378,8 +380,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ac->scene = scene;
if (scene) {
ac->markers = ED_context_get_markers(C);
- ac->obact = (scene->basact) ? scene->basact->object : NULL;
}
+ ac->scene_layer = CTX_data_scene_layer(C);
+ ac->obact = (ac->scene_layer->basact) ? ac->scene_layer->basact->object : NULL;
ac->sa = sa;
ac->ar = ar;
ac->sl = sl;
@@ -601,7 +604,7 @@ static bAnimListElem *make_new_animlistelem(void *data, short datatype, ID *owne
}
case ANIMTYPE_OBJECT:
{
- BaseLegacy *base = (BaseLegacy *)data;
+ Base *base = (Base *)data;
Object *ob = base->object;
ale->flag = ob->flag;
@@ -1683,15 +1686,16 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
if (ads->filterflag & ADS_FILTER_GP_3DONLY) {
Scene *scene = (Scene *)ads->source;
- BaseLegacy *base;
-
+ SceneLayer *sl = (SceneLayer *)ac->scene_layer;
+ Base *base;
+
/* Active scene's GPencil block first - No parent item needed... */
if (scene->gpd) {
items += animdata_filter_gpencil_data(anim_data, ads, scene->gpd, filter_mode);
}
/* Objects in the scene */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
/* Only consider this object if it has got some GP data (saving on all the other tests) */
if (base->object && base->object->gpd) {
Object *ob = base->object;
@@ -1707,14 +1711,14 @@ static size_t animdata_filter_gpencil(bAnimContext *ac, ListBase *anim_data, voi
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((scene->lay & (ob->lay | base->lay)) == 0) continue;
+ if ((base->flag & BASE_VISIBLED) == 0) continue;
/* outliner restrict-flag */
if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
}
/* check selection and object type filters */
- if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == scene->basact)*/) ) {
+ if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == scene->basact)*/) ) {
/* only selected should be shown */
continue;
}
@@ -2573,7 +2577,7 @@ static size_t animdata_filter_ds_obanim(bAnimContext *ac, ListBase *anim_data, b
}
/* get animation channels from object2 */
-static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, BaseLegacy *base, int filter_mode)
+static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Base *base, int filter_mode)
{
ListBase tmp_data = {NULL, NULL};
Object *ob = base->object;
@@ -2629,7 +2633,7 @@ static size_t animdata_filter_dopesheet_ob(bAnimContext *ac, ListBase *anim_data
if (filter_mode & ANIMFILTER_LIST_CHANNELS) {
/* check if filtering by selection */
// XXX: double-check on this - most of the time, a lot of tools need to filter out these channels!
- if (ANIMCHANNEL_SELOK((base->flag_legacy & SELECT))) {
+ if (ANIMCHANNEL_SELOK((base->flag & BASE_SELECTED))) {
/* check if filtering by active status */
if (ANIMCHANNEL_ACTIVEOK(ob)) {
ANIMCHANNEL_NEW_CHANNEL(base, ANIMTYPE_OBJECT, ob);
@@ -2853,7 +2857,7 @@ static size_t animdata_filter_dopesheet_movieclips(bAnimContext *ac, ListBase *a
}
/* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
-static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy *base, int filter_mode)
+static bool animdata_filter_base_is_ok(bDopeSheet *ads, Base *base, int filter_mode)
{
Object *ob = base->object;
@@ -2871,7 +2875,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy
*/
if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
/* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((scene->lay & (ob->lay | base->lay)) == 0)
+ if ((base->flag & BASE_VISIBLED) == 0)
return false;
/* outliner restrict-flag */
@@ -2906,7 +2910,7 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy
}
/* check selection and object type filters */
- if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag_legacy & SELECT) /*|| (base == sce->basact)*/)) {
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & BASE_SELECTED) /*|| (base == sce->basact)*/)) {
/* only selected should be shown */
return false;
}
@@ -2927,28 +2931,28 @@ static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, BaseLegacy
/* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
{
- const BaseLegacy *b1 = *((const BaseLegacy **)base1_ptr);
- const BaseLegacy *b2 = *((const BaseLegacy **)base2_ptr);
+ const Base *b1 = *((const Base **)base1_ptr);
+ const Base *b2 = *((const Base **)base2_ptr);
return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
}
/* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
-static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
+static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, SceneLayer *sl, int filter_mode, size_t *r_usable_bases)
{
/* Create an array with space for all the bases, but only containing the usable ones */
- size_t tot_bases = BLI_listbase_count(&scene->base);
+ size_t tot_bases = BLI_listbase_count(&sl->object_bases);
size_t num_bases = 0;
- BaseLegacy **sorted_bases = MEM_mallocN(sizeof(BaseLegacy *) * tot_bases, "Dopesheet Usable Sorted Bases");
- for (BaseLegacy *base = scene->base.first; base; base = base->next) {
- if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
sorted_bases[num_bases++] = base;
}
}
/* Sort this list of pointers (based on the names) */
- qsort(sorted_bases, num_bases, sizeof(BaseLegacy *), ds_base_sorting_cmp);
+ qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
/* Return list of sorted bases */
*r_usable_bases = num_bases;
@@ -2960,8 +2964,9 @@ static BaseLegacy **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scen
static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
Scene *scene = (Scene *)ads->source;
+ SceneLayer *sl = (SceneLayer *)ac->scene_layer;
size_t items = 0;
-
+
/* check that we do indeed have a scene */
if ((ads->source == NULL) || (GS(ads->source->name) != ID_SCE)) {
printf("Dope Sheet Error: No scene!\n");
@@ -2998,14 +3003,14 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
* - Don't do this if there's just a single object
*/
if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
- (scene->base.first != scene->base.last))
+ (sl->object_bases.first != sl->object_bases.last))
{
/* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
// TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
- BaseLegacy **sorted_bases;
+ Base **sorted_bases;
size_t num_bases;
- sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
+ sorted_bases = animdata_filter_ds_sorted_bases(ads, sl, filter_mode, &num_bases);
if (sorted_bases) {
/* Add the necessary channels for these bases... */
for (size_t i = 0; i < num_bases; i++) {
@@ -3022,8 +3027,8 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
/* Filter and add contents of each base (i.e. object) without them sorting first
* NOTE: This saves performance in cases where order doesn't matter
*/
- for (BaseLegacy *base = scene->base.first; base; base = base->next) {
- if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, base, filter_mode)) {
/* since we're still here, this object should be usable */
items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
}
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index ef9c2ced580..9d7d1535eb3 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -56,9 +56,11 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "UI_interface.h"
#include "UI_interface_icons.h"
#include "UI_view2d.h"
@@ -348,19 +350,24 @@ static void draw_marker(
if (flag & DRAW_MARKERS_LINES)
#endif
{
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
setlinestyle(3);
- if (marker->flag & SELECT)
- glColor4ub(255, 255, 255, 96);
- else
- glColor4ub(0, 0, 0, 96);
-
- glBegin(GL_LINES);
- glVertex2f(xpos + 0.5f, 12.0f);
- glVertex2f(xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
- glEnd();
-
+ if (marker->flag & SELECT) {
+ immUniformColor4ub(255, 255, 255, 96);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 96);
+ }
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, xpos + 0.5f, 12.0f);
+ immVertex2f(pos, xpos + 0.5f, (v2d->cur.ymax + 12.0f) * yscale);
+ immEnd();
setlinestyle(0);
+
+ immUnbindProgram();
}
/* 5 px to offset icon to align properly, space / pixels corrects for zoom */
@@ -438,21 +445,27 @@ void ED_markers_draw(const bContext *C, int flag)
v2d = UI_view2d_fromcontext(C);
if (flag & DRAW_MARKERS_MARGIN) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
const unsigned char shade[4] = {0, 0, 0, 16};
- glColor4ubv(shade);
+ immUniformColor4ubv(shade);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glRectf(v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
+ immRectf(pos, v2d->cur.xmin, 0, v2d->cur.xmax, UI_MARKER_MARGIN_Y);
glDisable(GL_BLEND);
+
+ immUnbindProgram();
}
/* no time correction for framelen! space is drawn with old values */
ypixels = BLI_rcti_size_y(&v2d->mask);
UI_view2d_scale_get(v2d, &xscale, &yscale);
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ gpuPushMatrix();
+ gpuScale2f(1.0f / xscale, 1.0f);
/* x-bounds with offset for text (adjust for long string, avoid checking string width) */
font_width_max = (10 * UI_DPI_FAC) / xscale;
@@ -475,7 +488,7 @@ void ED_markers_draw(const bContext *C, int flag)
}
}
- glScalef(xscale, 1.0f, 1.0f);
+ gpuPopMatrix();
}
/* ************************ Marker Wrappers API ********************* */
diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c
index c0d6963acbb..0eb6508f7b2 100644
--- a/source/blender/editors/animation/anim_ops.c
+++ b/source/blender/editors/animation/anim_ops.c
@@ -95,7 +95,7 @@ static void change_frame_apply(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- int frame = RNA_int_get(op->ptr, "frame");
+ float frame = RNA_float_get(op->ptr, "frame");
bool do_snap = RNA_boolean_get(op->ptr, "snap");
if (do_snap && CTX_wm_space_seq(C)) {
@@ -103,10 +103,16 @@ static void change_frame_apply(bContext *C, wmOperator *op)
}
/* set the new frame number */
- CFRA = frame;
+ if (scene->r.flag & SCER_SHOW_SUBFRAME) {
+ CFRA = (int)frame;
+ SUBFRA = frame - (int)frame;
+ }
+ else {
+ CFRA = iroundf(frame);
+ SUBFRA = 0.0f;
+ }
FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.0f;
-
+
/* do updates */
BKE_sound_seek_scene(bmain, scene);
WM_event_add_notifier(C, NC_SCENE | ND_FRAME, scene);
@@ -125,19 +131,16 @@ static int change_frame_exec(bContext *C, wmOperator *op)
/* ---- */
/* Get frame from mouse coordinates */
-static int frame_from_event(bContext *C, const wmEvent *event)
+static float frame_from_event(bContext *C, const wmEvent *event)
{
ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
- float viewx;
- int frame;
+ float frame;
/* convert from region coordinates to View2D 'tot' space */
- viewx = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
-
- /* round result to nearest int (frames are ints!) */
- frame = iroundf(viewx);
+ frame = UI_view2d_region_to_view_x(&region->v2d, event->mval[0]);
+ /* respect preview range restrictions (if only allowed to move around within that range) */
if (scene->r.flag & SCER_LOCK_FRAME_SELECTION) {
CLAMP(frame, PSFRA, PEFRA);
}
@@ -187,7 +190,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
* as user could click on a single frame (jump to frame) as well as
* click-dragging over a range (modal scrubbing).
*/
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_seq_preview_begin(C, event);
@@ -215,7 +218,7 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
case MOUSEMOVE:
- RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
+ RNA_float_set(op->ptr, "frame", frame_from_event(C, event));
change_frame_apply(C, op);
break;
@@ -268,7 +271,7 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
ot->undo_group = "FRAME_CHANGE";
/* rna */
- ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+ ot->prop = RNA_def_float(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index c8d141eab07..5f96f95e95b 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -470,7 +470,7 @@ void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type,
bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
- if (!(draw_fill || draw_outline)) return; /* TODO: assert this? */
+ BLI_assert(draw_fill || draw_outline);
/* tweak size of keyframe shape according to type of keyframe
* - 'proper' keyframes have key_type = 0, so get drawn at full size
@@ -484,8 +484,7 @@ void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type,
break;
case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes (but by less than for breakdowns) */
- //size *= 0.72f;
- size *= 0.95f;
+ size *= 0.925f;
break;
case BEZT_KEYTYPE_EXTREME: /* slightly larger */
@@ -559,8 +558,9 @@ void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type,
static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
{
- const float iconsize = U.widget_unit * 0.25f * yscale_fac;
- const float mhsize = iconsize * 0.7f;
+ const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
+ const float half_icon_sz = 0.5f * icon_sz;
+ const float smaller_sz = 0.35f * icon_sz;
glEnable(GL_BLEND);
@@ -593,12 +593,12 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
/* draw "moving hold" long-keyframe block - slightly smaller */
immUniformColor4fv(ab->sel ? sel_mhcol : unsel_mhcol);
- immRectf(pos_id, ab->start, ypos - mhsize, ab->end, ypos + mhsize);
+ immRectf(pos_id, ab->start, ypos - smaller_sz, ab->end, ypos + smaller_sz);
}
else {
/* draw standard long-keyframe block */
immUniformColor4fv(ab->sel ? sel_color : unsel_color);
- immRectf(pos_id, ab->start, ypos - iconsize, ab->end, ypos + iconsize);
+ immRectf(pos_id, ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz);
}
}
}
@@ -629,7 +629,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
- draw_keyframe_shape(ak->cfra, ypos, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
+ draw_keyframe_shape(ak->cfra, ypos, icon_sz, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
pos_id, size_id, color_id, outline_color_id);
}
}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index d75193a46ff..8c1083dc290 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -247,8 +247,10 @@ void armature_select_mirrored_ex(struct bArmature *arm, const int flag);
void armature_select_mirrored(struct bArmature *arm);
void armature_tag_unselect(struct bArmature *arm);
-void *get_nearest_bone(struct bContext *C, short findunsel, int x, int y);
-void *get_bone_from_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest);
+void *get_nearest_bone(struct bContext *C, const int xy[2], bool findunsel);
+void *get_bone_from_selectbuffer(
+ struct Scene *scene, struct Base *base, const unsigned int *buffer, short hits,
+ bool findunsel, bool do_nearest);
int bone_looper(struct Object *ob, struct Bone *bone, void *data,
int (*bone_func)(struct Object *, struct Bone *, void *));
diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index fa192ed6f36..c928508237d 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -362,7 +362,7 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
arm = ob->data;
- ListBase bones_names= {NULL};
+ ListBase bones_names = {NULL};
CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
{
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 1f994a7f13e..b78adba408c 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -74,7 +74,9 @@ Bone *get_indexed_bone(Object *ob, int index)
/* See if there are any selected bones in this buffer */
/* only bones from base are checked on */
-void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
+void *get_bone_from_selectbuffer(
+ Scene *scene, Base *base, const unsigned int *buffer, short hits,
+ bool findunsel, bool do_nearest)
{
Object *obedit = scene->obedit; // XXX get from context
Bone *bone;
@@ -103,8 +105,8 @@ void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *b
sel = (bone->flag & BONE_SELECTED);
else
sel = !(bone->flag & BONE_SELECTED);
-
- data = bone;
+
+ data = bone;
}
else {
data = NULL;
@@ -162,7 +164,7 @@ void *get_bone_from_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *b
/* used by posemode as well editmode */
/* only checks scene->basact! */
/* x and y are mouse coords (area space) */
-void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
+void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel)
{
ViewContext vc;
rcti rect;
@@ -172,13 +174,13 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
view3d_set_viewcontext(C, &vc);
// rect.xmin = ... mouseco!
- rect.xmin = rect.xmax = x;
- rect.ymin = rect.ymax = y;
+ rect.xmin = rect.xmax = xy[0];
+ rect.ymin = rect.ymax = xy[1];
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
if (hits > 0)
- return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true);
+ return get_bone_from_selectbuffer(vc.scene, vc.sl->basact, buffer, hits, findunsel, true);
return NULL;
}
@@ -197,10 +199,7 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
view3d_operator_needs_opengl(C);
- if (extend)
- bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
- else
- bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
+ bone = get_nearest_bone(C, event->mval, !extend);
if (!bone)
return OPERATOR_CANCELLED;
@@ -276,10 +275,24 @@ void ARMATURE_OT_select_linked(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
}
+/* utility function for get_nearest_editbonepoint */
+static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
+{
+ return hits12;
+}
+
+static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
+{
+ const int offs = 4 * hits12;
+ memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
+ return hits5;
+}
+
/* does bones and points */
/* note that BONE ROOT only gets drawn for root bones (or without IK) */
-static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
- ListBase *edbo, int findunsel, int *selmask)
+static EditBone *get_nearest_editbonepoint(
+ ViewContext *vc, const int mval[2],
+ ListBase *edbo, bool findunsel, bool use_cycle, int *r_selmask)
{
bArmature *arm = (bArmature *)vc->obedit->data;
EditBone *ebone_next_act = arm->act_edbone;
@@ -289,7 +302,9 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
unsigned int buffer[MAXPICKBUF];
unsigned int hitresult, besthitresult = BONESEL_NOSEL;
int i, mindep = 5;
- short hits;
+ int hits12, hits5 = 0;
+
+ static int last_mval[2] = {-100, -100};
/* find the bone after the current active bone, so as to bump up its chances in selection.
* this way overlapping bones will cycle selection state as with objects. */
@@ -303,22 +318,59 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
ebone_next_act = NULL;
}
- rect.xmin = mval[0] - 5;
- rect.xmax = mval[0] + 5;
- rect.ymin = mval[1] - 5;
- rect.ymax = mval[1] + 5;
-
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
- if (hits == 0) {
- rect.xmin = mval[0] - 12;
- rect.xmax = mval[0] + 12;
- rect.ymin = mval[1] - 12;
- rect.ymax = mval[1] + 12;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
+ bool do_nearest = false;
+
+ /* define if we use solid nearest select or not */
+ if (use_cycle) {
+ if (vc->v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
+ if (len_manhattan_v2v2_int(mval, last_mval) < 3) {
+ do_nearest = false;
+ }
+ }
+ copy_v2_v2_int(last_mval, mval);
+ }
+ else {
+ if (vc->v3d->drawtype > OB_WIRE) {
+ do_nearest = true;
+ }
}
+
+ /* matching logic from 'mixed_bones_object_selectbuffer' */
+ const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ int hits = 0;
+
+ /* we _must_ end cache before return, use 'goto cache_end' */
+ view3d_opengl_select_cache_begin();
+
+ BLI_rcti_init_pt_radius(&rect, mval, 12);
+ hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
+ if (hits12 == 1) {
+ hits = selectbuffer_ret_hits_12(buffer, hits12);
+ goto cache_end;
+ }
+ else if (hits12 > 0) {
+ int offs;
+
+ offs = 4 * hits12;
+ BLI_rcti_init_pt_radius(&rect, mval, 5);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
+
+ if (hits5 == 1) {
+ hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
+ goto cache_end;
+ }
+
+ if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits12, hits5); goto cache_end; }
+ else { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; }
+ }
+
+cache_end:
+ view3d_opengl_select_cache_end();
+
/* See if there are any selected bones in this group */
if (hits > 0) {
-
+
if (hits == 1) {
if (!(buffer[3] & BONESEL_NOSEL))
besthitresult = buffer[3];
@@ -375,17 +427,17 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
ebone = BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
- *selmask = 0;
+ *r_selmask = 0;
if (besthitresult & BONESEL_ROOT)
- *selmask |= BONE_ROOTSEL;
+ *r_selmask |= BONE_ROOTSEL;
if (besthitresult & BONESEL_TIP)
- *selmask |= BONE_TIPSEL;
+ *r_selmask |= BONE_TIPSEL;
if (besthitresult & BONESEL_BONE)
- *selmask |= BONE_SELECTED;
+ *r_selmask |= BONE_SELECTED;
return ebone;
}
}
- *selmask = 0;
+ *r_selmask = 0;
return NULL;
}
@@ -439,8 +491,8 @@ bool ED_armature_select_pick(bContext *C, const int mval[2], bool extend, bool d
if (BIF_sk_selectStroke(C, mval, extend)) {
return true;
}
-
- nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
+
+ nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, true, true, &selmask);
if (nearBone) {
if (!extend && !deselect && !toggle) {
@@ -1202,7 +1254,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const
view3d_operator_needs_opengl(C);
ebone_src = arm->act_edbone;
- ebone_dst = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
+ ebone_dst = get_nearest_bone(C, event->mval, false);
/* fallback to object selection */
if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c
index 4d9ba351c3a..f42ce147431 100644
--- a/source/blender/editors/armature/editarmature_sketch.c
+++ b/source/blender/editors/armature/editarmature_sketch.c
@@ -41,6 +41,7 @@
#include "ED_screen.h"
#include "BIF_gl.h"
+#include "BIF_glutil.h"
#include "ED_armature.h"
#include "armature_intern.h"
#include "BIF_retarget.h"
@@ -53,6 +54,9 @@
#include "WM_types.h"
#include "GPU_select.h"
+#include "GPU_matrix.h"
+#include "GPU_batch.h"
+#include "GPU_immediate.h"
typedef int (*GestureDetectFct)(bContext *, SK_Gesture *, SK_Sketch *);
typedef void (*GestureApplyFct)(bContext *, SK_Gesture *, SK_Sketch *);
@@ -420,7 +424,6 @@ static void sk_retargetStroke(bContext *C, SK_Stroke *stk)
}
/**************************************************************/
-
static void sk_cancelStroke(SK_Sketch *sketch)
{
if (sketch->active_stroke != NULL) {
@@ -435,17 +438,33 @@ static float sk_clampPointSize(SK_Point *pt, float size)
return max_ff(size * pt->size, size / 2);
}
-static void sk_drawPoint(GLUquadric *quad, SK_Point *pt, float size)
+static void sk_drawPoint(SK_Point *pt, float size, float color[4])
{
- glTranslate3fv(pt->p);
- gluSphere(quad, sk_clampPointSize(pt, size), 8, 8);
+ Batch *batch = NULL;
+
+ gpuTranslate3fv(pt->p);
+
+ gpuPushMatrix();
+
+ gpuScaleUniform(sk_clampPointSize(pt, size));
+
+ batch = Batch_get_sphere(0);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ Batch_Uniform4fv(batch, "color", color);
+
+ Batch_draw(batch);
+
+ gpuPopMatrix();
}
-static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float size)
+static void sk_drawEdge(SK_Point *pt0, SK_Point *pt1, float size, float color[4])
{
- float vec1[3], vec2[3] = {0, 0, 1}, axis[3];
+ float vec1[3], vec2[3] = { 0, 0, 1 }, axis[3];
float angle, length;
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
sub_v3_v3v3(vec1, pt1->p, pt0->p);
length = normalize_v3(vec1);
cross_v3_v3v3(axis, vec2, vec1);
@@ -454,19 +473,26 @@ static void sk_drawEdge(GLUquadric *quad, SK_Point *pt0, SK_Point *pt1, float si
axis[1] = 1;
}
- angle = angle_normalized_v3v3(vec2, vec1);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
- glRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
+ angle = angle_normalized_v3v3(vec2, vec1);
+ gpuRotate3fv(angle * (float)(180.0 / M_PI) + 180.0f, axis);
+ imm_cylinder(pos, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
- gluCylinder(quad, sk_clampPointSize(pt1, size), sk_clampPointSize(pt0, size), length, 8, 8);
+ immUnbindProgram();
}
-static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float height)
+static void sk_drawNormal(SK_Point *pt, float size, float height)
{
- float vec2[3] = {0, 0, 1}, axis[3];
+ float vec2[3] = { 0, 0, 1 }, axis[3];
float angle;
-
- glPushMatrix();
+ float color[3] = { 0.0f, 1.0f, 1.0f };
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ gpuPushMatrix();
cross_v3_v3v3(axis, vec2, pt->no);
@@ -474,41 +500,44 @@ static void sk_drawNormal(GLUquadric *quad, SK_Point *pt, float size, float heig
axis[1] = 1;
}
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+
angle = angle_normalized_v3v3(vec2, pt->no);
+ gpuRotate3fv(angle * (float)(180.0 / M_PI), axis);
- glRotate3fv(angle * (float)(180.0 / M_PI), axis);
+ imm_cylinder(pos, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
- glColor3f(0, 1, 1);
- gluCylinder(quad, sk_clampPointSize(pt, size), 0, sk_clampPointSize(pt, height), 10, 2);
+ immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
}
static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int end)
{
float rgb[3];
+ float zero_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
int i;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
if (id != -1) {
GPU_select_load_id(id);
for (i = 0; i < stk->nb_points; i++) {
- glPushMatrix();
+ gpuPushMatrix();
- sk_drawPoint(quad, stk->points + i, 0.1);
+ sk_drawPoint(stk->points + i, 0.1, zero_color);
if (i > 0) {
- sk_drawEdge(quad, stk->points + i - 1, stk->points + i, 0.1);
+ sk_drawEdge(stk->points + i - 1, stk->points + i, 0.1, zero_color);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
- float d_rgb[3] = {1, 1, 1};
+ float d_rgb[3] = { 1, 1, 1 };
+ float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
copy_v3_v3(rgb, color);
sub_v3_v3(d_rgb, rgb);
@@ -517,48 +546,44 @@ static void sk_drawStroke(SK_Stroke *stk, int id, float color[3], int start, int
for (i = 0; i < stk->nb_points; i++) {
SK_Point *pt = stk->points + i;
- glPushMatrix();
+ gpuPushMatrix();
if (pt->type == PT_EXACT) {
- glColor3f(0, 0, 0);
- sk_drawPoint(quad, pt, 0.15);
- sk_drawNormal(quad, pt, 0.05, 0.9);
+ sk_drawPoint(pt, 0.15, zero_color);
+ sk_drawNormal(pt, 0.05, 0.9);
}
if (i >= start && i <= end) {
- glColor3f(0.3, 0.3, 0.3);
+ copy_v4_fl4(tmp_color, 0.3f, 0.3f, 0.3f, 1.0f);
}
else {
- glColor3fv(rgb);
+ copy_v4_fl4(tmp_color, rgb[0], rgb[1], rgb[2], 1.0f);
}
if (pt->type != PT_EXACT) {
-
- sk_drawPoint(quad, pt, 0.1);
+ sk_drawPoint(pt, 0.1, tmp_color);
}
if (i > 0) {
- sk_drawEdge(quad, pt - 1, pt, 0.1);
+ sk_drawEdge(pt - 1, pt, 0.1, tmp_color);
}
- glPopMatrix();
+ gpuPopMatrix();
add_v3_v3(rgb, d_rgb);
}
}
- gluDeleteQuadric(quad);
}
static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *iter, NextSubdivisionFunc next_subdividion)
{
SK_Stroke *stk = ((SK_StrokeIterator *)iter)->stroke;
float head[3], tail[3];
+ float color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
int bone_start = 0;
int end = iter->length;
int index;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
iter->head(iter);
copy_v3_v3(head, iter->p);
@@ -567,22 +592,19 @@ static void drawSubdividedStrokeBy(ToolSettings *toolsettings, BArcIterator *ite
while (index != -1) {
SK_Point *pt = stk->points + index;
- glPushMatrix();
+ gpuPushMatrix();
- glColor3f(0, 1, 0);
- sk_drawPoint(quad, pt, 0.15);
+ sk_drawPoint(pt, 0.15, color);
- sk_drawNormal(quad, pt, 0.05, 0.9);
+ sk_drawNormal(pt, 0.05, 0.9);
- glPopMatrix();
+ gpuPopMatrix();
copy_v3_v3(head, tail);
bone_start = index; // start next bone from current index
index = next_subdividion(toolsettings, iter, bone_start, end, head, tail);
}
-
- gluDeleteQuadric(quad);
}
static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk)
@@ -1907,12 +1929,9 @@ static bool sk_selectStroke(bContext *C, SK_Sketch *sketch, const int mval[2], c
view3d_set_viewcontext(C, &vc);
- rect.xmin = mval[0] - 5;
- rect.xmax = mval[0] + 5;
- rect.ymin = mval[1] - 5;
- rect.ymax = mval[1] + 5;
+ BLI_rcti_init_pt_radius(&rect, mval, 5);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
if (hits > 0) {
int besthitresult = -1;
@@ -1978,9 +1997,9 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
GPU_select_load_id(-1);
}
else {
- float selected_rgb[3] = {1, 0, 0};
- float unselected_rgb[3] = {1, 0.5, 0};
-
+ float selected_rgb[3] = { 1, 0, 0 };
+ float unselected_rgb[3] = { 1, 0.5, 0 };
+ float tmp_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
for (stk = sketch->strokes.first; stk; stk = stk->next) {
int start = -1;
int end = -1;
@@ -2004,75 +2023,37 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch,
}
if (last != NULL) {
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
-
- glPushMatrix();
+ gpuPushMatrix();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
switch (sketch->next_point.mode) {
- case PT_SNAP:
- glColor3f(0, 1, 0);
- break;
- case PT_PROJECT:
- glColor3f(0, 0, 0);
- break;
+ case PT_SNAP:
+ copy_v4_fl4(tmp_color, 0.0f, 1.0f, 0.0f, 1.0f);
+ break;
+ case PT_PROJECT:
+ copy_v4_fl4(tmp_color, 0.0f, 0.0f, 0.0f, 1.0f);
+ break;
}
- sk_drawPoint(quad, &sketch->next_point, 0.1);
-
- glColor4f(selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
+ sk_drawPoint(&sketch->next_point, 0.1, tmp_color);
- sk_drawEdge(quad, last, &sketch->next_point, 0.1);
+ copy_v4_fl4(tmp_color, selected_rgb[0], selected_rgb[1], selected_rgb[2], 0.3);
+ sk_drawEdge(last, &sketch->next_point, 0.1f, tmp_color);
glDisable(GL_BLEND);
- glPopMatrix();
-
- gluDeleteQuadric(quad);
+ gpuPopMatrix();
}
}
}
-#if 0
- if (BLI_listbase_is_empty(&sketch->depth_peels) == false) {
- float colors[8][3] = {
- {1, 0, 0},
- {0, 1, 0},
- {0, 0, 1},
- {1, 1, 0},
- {1, 0, 1},
- {0, 1, 1},
- {1, 1, 1},
- {0, 0, 0}
- };
- DepthPeel *p;
- GLUquadric *quad = gluNewQuadric();
- gluQuadricNormals(quad, GLU_SMOOTH);
-
- for (p = sketch->depth_peels.first; p; p = p->next)
- {
- int index = GET_INT_FROM_POINTER(p->ob);
- index = (index >> 5) & 7;
-
- glColor3fv(colors[index]);
- glPushMatrix();
- glTranslate3fv(p->p);
- gluSphere(quad, 0.02, 8, 8);
- glPopMatrix();
- }
-
- gluDeleteQuadric(quad);
- }
-#endif
-
glDisable(GL_DEPTH_TEST);
/* only draw gesture in active area */
if (sketch->gesture != NULL /* && area_is_active_area(G.vd->area) */) {
- float gesture_rgb[3] = {0, 0.5, 1};
+ float gesture_rgb[3] = { 0, 0.5, 1 };
sk_drawStroke(sketch->gesture, -1, gesture_rgb, -1, -1);
}
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 903d309cb1f..fdc58f6e253 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -132,8 +132,9 @@ void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
/* called from editview.c, for mode-less pose selection */
/* assumes scene obact and basact is still on old situation */
-int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer, short hits,
- bool extend, bool deselect, bool toggle, bool do_nearest)
+bool ED_do_pose_selectbuffer(
+ Scene *scene, SceneLayer *sl, Base *base, const unsigned int *buffer, short hits,
+ bool extend, bool deselect, bool toggle, bool do_nearest)
{
Object *ob = base->object;
Bone *nearBone;
@@ -144,7 +145,7 @@ int ED_do_pose_selectbuffer(Scene *scene, BaseLegacy *base, unsigned int *buffer
/* if the bone cannot be affected, don't do anything */
if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
- Object *ob_act = OBACT;
+ Object *ob_act = OBACT_NEW;
bArmature *arm = ob->data;
/* since we do unified select, we don't shift+select a bone if the
@@ -280,12 +281,9 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
const bool extend = RNA_boolean_get(op->ptr, "extend");
view3d_operator_needs_opengl(C);
-
- if (extend)
- bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
- else
- bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
-
+
+ bone = get_nearest_bone(C, event->mval, !extend);
+
if (!bone)
return OPERATOR_CANCELLED;
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index 8e8345d34c9..21cb405c32b 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -98,8 +98,11 @@ typedef struct tPoseSlideOp {
int prevFrame; /* frame before current frame (blend-from) */
int nextFrame; /* frame after current frame (blend-to) */
- int mode; /* sliding mode (ePoseSlide_Modes) */
- int flag; /* unused for now, but can later get used for storing runtime settings.... */
+ short mode; /* sliding mode (ePoseSlide_Modes) */
+ short flag; /* unused for now, but can later get used for storing runtime settings.... */
+
+ short channels; /* which transforms/channels are affected (ePoseSlide_Channels) */
+ short axislock; /* axis-limits for transforms (ePoseSlide_AxisLock) */
float percentage; /* 0-1 value for determining the influence of whatever is relevant */
@@ -113,6 +116,49 @@ typedef enum ePoseSlide_Modes {
POSESLIDE_BREAKDOWN, /* slide between the endpoint poses, finding a 'soft' spot */
} ePoseSlide_Modes;
+
+/* Transforms/Channels to Affect */
+typedef enum ePoseSlide_Channels {
+ PS_TFM_ALL = 0, /* All transforms and properties */
+
+ PS_TFM_LOC, /* Loc/Rot/Scale */
+ PS_TFM_ROT,
+ PS_TFM_SIZE,
+
+ PS_TFM_BBONE_SHAPE, /* Bendy Bones */
+
+ PS_TFM_PROPS /* Custom Properties */
+} ePoseSlide_Channels;
+
+/* Property enum for ePoseSlide_Channels */
+static EnumPropertyItem prop_channels_types[] = {
+ {PS_TFM_ALL, "ALL", 0, "All Properties",
+ "All properties, including transforms, bendy bone shape, and custom properties"},
+ {PS_TFM_LOC, "LOC", 0, "Location", "Location only"},
+ {PS_TFM_ROT, "ROT", 0, "Rotation", "Rotation only"},
+ {PS_TFM_SIZE, "SIZE", 0, "Scale", "Scale only"},
+ {PS_TFM_BBONE_SHAPE, "BBONE", 0, "Bendy Bone", "Bendy Bone shape properties"},
+ {PS_TFM_PROPS, "CUSTOM", 0, "Custom Properties", "Custom properties"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+/* Axis Locks */
+typedef enum ePoseSlide_AxisLock {
+ PS_LOCK_X = (1 << 0),
+ PS_LOCK_Y = (1 << 1),
+ PS_LOCK_Z = (1 << 2)
+} ePoseSlide_AxisLock;
+
+/* Property enum for ePoseSlide_AxisLock */
+static EnumPropertyItem prop_axis_lock_types[] = {
+ {0, "FREE", 0, "Free", "All axes are affected"},
+ {PS_LOCK_X, "X", 0, "X", "Only X-axis transforms are affected"},
+ {PS_LOCK_Y, "Y", 0, "Y", "Only Y-axis transforms are affected"},
+ {PS_LOCK_Z, "Z", 0, "Z", "Only Z-axis transforms are affected"},
+ /* TODO: Combinations? */
+ {0, NULL, 0, NULL, NULL}
+};
+
/* ------------------------------------ */
/* operator init */
@@ -139,6 +185,10 @@ static int pose_slide_init(bContext *C, wmOperator *op, short mode)
pso->prevFrame = RNA_int_get(op->ptr, "prev_frame");
pso->nextFrame = RNA_int_get(op->ptr, "next_frame");
+ /* get the set of properties/axes that can be operated on */
+ pso->channels = RNA_enum_get(op->ptr, "channels");
+ pso->axislock = RNA_enum_get(op->ptr, "axis_lock");
+
/* check the settings from the context */
if (ELEM(NULL, pso->ob, pso->arm, pso->ob->adt, pso->ob->adt->action))
return 0;
@@ -293,10 +343,20 @@ static void pose_slide_apply_vec3(tPoseSlideOp *pso, tPChanFCurveLink *pfl, floa
/* using this path, find each matching F-Curve for the variables we're interested in */
while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
FCurve *fcu = (FCurve *)ld->data;
-
- /* just work on these channels one by one... there's no interaction between values */
+ const int idx = fcu->array_index;
+ const int lock = pso->axislock;
+
+ /* check if this F-Curve is ok given the current axis locks */
BLI_assert(fcu->array_index < 3);
- pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]);
+
+ if ((lock == 0) ||
+ ((lock & PS_LOCK_X) && (idx == 0)) ||
+ ((lock & PS_LOCK_Y) && (idx == 1)) ||
+ ((lock & PS_LOCK_Z) && (idx == 2)))
+ {
+ /* just work on these channels one by one... there's no interaction between values */
+ pose_slide_apply_val(pso, fcu, &vec[fcu->array_index]);
+ }
}
/* free the temp path we got */
@@ -494,17 +554,17 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
*/
bPoseChannel *pchan = pfl->pchan;
- if (pchan->flag & POSE_LOC) {
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_LOC) && (pchan->flag & POSE_LOC)) {
/* calculate these for the 'location' vector, and use location curves */
pose_slide_apply_vec3(pso, pfl, pchan->loc, "location");
}
- if (pchan->flag & POSE_SIZE) {
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_SIZE) && (pchan->flag & POSE_SIZE)) {
/* calculate these for the 'scale' vector, and use scale curves */
pose_slide_apply_vec3(pso, pfl, pchan->size, "scale");
}
- if (pchan->flag & POSE_ROT) {
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_ROT) && (pchan->flag & POSE_ROT)) {
/* everything depends on the rotation mode */
if (pchan->rotmode > 0) {
/* eulers - so calculate these for the 'eul' vector, and use euler_rotation curves */
@@ -519,12 +579,12 @@ static void pose_slide_apply(bContext *C, tPoseSlideOp *pso)
}
}
- if (pchan->flag & POSE_BBONE_SHAPE) {
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE) && (pchan->flag & POSE_BBONE_SHAPE)) {
/* bbone properties - they all start a "bbone_" prefix */
pose_slide_apply_props(pso, pfl, "bbone_");
}
- if (pfl->oldprops) {
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_PROPS) && (pfl->oldprops)) {
/* not strictly a transform, but custom properties contribute to the pose produced in many rigs
* (e.g. the facial rigs used in Sintel)
*/
@@ -553,9 +613,12 @@ static void pose_slide_reset(tPoseSlideOp *pso)
/* ------------------------------------ */
/* draw percentage indicator in header */
+// TODO: Include hints about locks here...
static void pose_slide_draw_status(tPoseSlideOp *pso)
{
char status_str[UI_MAX_DRAW_STR];
+ char limits_str[UI_MAX_DRAW_STR];
+ char axis_str[50];
char mode_str[32];
switch (pso->mode) {
@@ -575,16 +638,58 @@ static void pose_slide_draw_status(tPoseSlideOp *pso)
break;
}
+ switch (pso->axislock) {
+ case PS_LOCK_X:
+ BLI_strncpy(axis_str, "[X]/Y/Z axis only (X to clear)", sizeof(axis_str));
+ break;
+ case PS_LOCK_Y:
+ BLI_strncpy(axis_str, "X/[Y]/Z axis only (Y to clear)", sizeof(axis_str));
+ break;
+ case PS_LOCK_Z:
+ BLI_strncpy(axis_str, "X/Y/[Z] axis only (Z to clear)", sizeof(axis_str));
+ break;
+
+ default:
+ if (ELEM(pso->channels, PS_TFM_LOC, PS_TFM_ROT, PS_TFM_SIZE)) {
+ BLI_strncpy(axis_str, "X/Y/Z = Axis Constraint", sizeof(axis_str));
+ }
+ else {
+ axis_str[0] = '\0';
+ }
+ break;
+ }
+
+ switch (pso->channels) {
+ case PS_TFM_LOC:
+ BLI_snprintf(limits_str, sizeof(limits_str), "[G]/R/S/B/C - Location only (G to clear) | %s", axis_str);
+ break;
+ case PS_TFM_ROT:
+ BLI_snprintf(limits_str, sizeof(limits_str), "G/[R]/S/B/C - Rotation only (R to clear) | %s", axis_str);
+ break;
+ case PS_TFM_SIZE:
+ BLI_snprintf(limits_str, sizeof(limits_str), "G/R/[S]/B/C - Scale only (S to clear) | %s", axis_str);
+ break;
+ case PS_TFM_BBONE_SHAPE:
+ BLI_strncpy(limits_str, "G/R/S/[B]/C - Bendy Bone properties only (B to clear) | %s", sizeof(limits_str));
+ break;
+ case PS_TFM_PROPS:
+ BLI_strncpy(limits_str, "G/R/S/B/[C] - Custom Properties only (C to clear) | %s", sizeof(limits_str));
+ break;
+ default:
+ BLI_strncpy(limits_str, "G/R/S/B/C - Limit to Transform/Property Set", sizeof(limits_str));
+ break;
+ }
+
if (hasNumInput(&pso->num)) {
Scene *scene = pso->scene;
char str_offs[NUM_STR_REP_LEN];
outputNumInput(&pso->num, str_offs, &scene->unit);
- BLI_snprintf(status_str, sizeof(status_str), "%s: %s", mode_str, str_offs);
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %s | %s", mode_str, str_offs, limits_str);
}
else {
- BLI_snprintf(status_str, sizeof(status_str), "%s: %d %%", mode_str, (int)(pso->percentage * 100.0f));
+ BLI_snprintf(status_str, sizeof(status_str), "%s: %d %% | %s", mode_str, (int)(pso->percentage * 100.0f), limits_str);
}
ED_area_headerprint(pso->sa, status_str);
@@ -675,11 +780,58 @@ static void pose_slide_mouse_update_percentage(tPoseSlideOp *pso, wmOperator *op
RNA_float_set(op->ptr, "percentage", pso->percentage);
}
+/* handle an event to toggle channels mode */
+static void pose_slide_toggle_channels_mode(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_Channels channel)
+{
+ /* Turn channel on or off? */
+ if (pso->channels == channel) {
+ /* Already limiting to transform only, so pressing this again turns it off */
+ pso->channels = PS_TFM_ALL;
+ }
+ else {
+ /* Only this set of channels */
+ pso->channels = channel;
+ }
+ RNA_enum_set(op->ptr, "channels", pso->channels);
+
+
+ /* Reset axis limits too for good measure */
+ pso->axislock = 0;
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+}
+
+/* handle an event to toggle axis locks - returns whether any change in state is needed */
+static bool pose_slide_toggle_axis_locks(wmOperator *op, tPoseSlideOp *pso, ePoseSlide_AxisLock axis)
+{
+ /* Axis can only be set when a transform is set - it doesn't make sense otherwise */
+ if (ELEM(pso->channels, PS_TFM_ALL, PS_TFM_BBONE_SHAPE, PS_TFM_PROPS)) {
+ pso->axislock = 0;
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+ return false;
+ }
+
+ /* Turn on or off? */
+ if (pso->axislock == axis) {
+ /* Already limiting on this axis, so turn off */
+ pso->axislock = 0;
+ }
+ else {
+ /* Only this axis */
+ pso->axislock = axis;
+ }
+ RNA_enum_set(op->ptr, "axis_lock", pso->axislock);
+
+ /* Setting changed, so pose update is needed */
+ return true;
+}
+
/* common code for modal() */
static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
tPoseSlideOp *pso = op->customdata;
wmWindow *win = CTX_wm_window(C);
+ bool do_pose_update = false;
+
const bool has_numinput = hasNumInput(&pso->num);
switch (event->type) {
@@ -718,7 +870,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* canceled! */
return OPERATOR_CANCELLED;
}
-
+
+ /* Percentage Chane... */
case MOUSEMOVE: /* calculate new position */
{
/* only handle mousemove if not doing numinput */
@@ -726,14 +879,8 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
/* update percentage based on position of mouse */
pose_slide_mouse_update_percentage(pso, op, event);
- /* update percentage indicator in header */
- pose_slide_draw_status(pso);
-
- /* reset transforms (to avoid accumulation errors) */
- pose_slide_reset(pso);
-
- /* apply... */
- pose_slide_apply(C, pso);
+ /* update pose to reflect the new values (see below) */
+ do_pose_update = true;
}
break;
}
@@ -751,16 +898,75 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
CLAMP(pso->percentage, 0.0f, 1.0f);
RNA_float_set(op->ptr, "percentage", pso->percentage);
- /* update percentage indicator in header */
- pose_slide_draw_status(pso);
-
- /* reset transforms (to avoid accumulation errors) */
- pose_slide_reset(pso);
-
- /* apply... */
- pose_slide_apply(C, pso);
+ /* Update pose to reflect the new values (see below) */
+ do_pose_update = true;
break;
}
+ else if (event->val == KM_PRESS) {
+ switch (event->type) {
+ /* Transform Channel Limits */
+ /* XXX: Replace these hardcoded hotkeys with a modalmap that can be customised */
+ case GKEY: /* Location */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_LOC);
+ do_pose_update = true;
+ break;
+ }
+ case RKEY: /* Rotation */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_ROT);
+ do_pose_update = true;
+ break;
+ }
+ case SKEY: /* Scale */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_SIZE);
+ do_pose_update = true;
+ break;
+ }
+ case BKEY: /* Bendy Bones */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_BBONE_SHAPE);
+ do_pose_update = true;
+ break;
+ }
+ case CKEY: /* Custom Properties */
+ {
+ pose_slide_toggle_channels_mode(op, pso, PS_TFM_PROPS);
+ do_pose_update = true;
+ break;
+ }
+
+
+ /* Axis Locks */
+ /* XXX: Hardcoded... */
+ case XKEY:
+ {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_X)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+ case YKEY:
+ {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Y)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+ case ZKEY:
+ {
+ if (pose_slide_toggle_axis_locks(op, pso, PS_LOCK_Z)) {
+ do_pose_update = true;
+ }
+ break;
+ }
+
+
+ default: /* Some other unhandled key... */
+ break;
+ }
+ }
else {
/* unhandled event - maybe it was some view manip? */
/* allow to pass through */
@@ -768,6 +974,19 @@ static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
}
+
+ /* perform pose updates - in response to some user action (e.g. pressing a key or moving the mouse) */
+ if (do_pose_update) {
+ /* update percentage indicator in header */
+ pose_slide_draw_status(pso);
+
+ /* reset transforms (to avoid accumulation errors) */
+ pose_slide_reset(pso);
+
+ /* apply... */
+ pose_slide_apply(C, pso);
+ }
+
/* still running... */
return OPERATOR_RUNNING_MODAL;
}
@@ -795,11 +1014,16 @@ static int pose_slide_exec_common(bContext *C, wmOperator *op, tPoseSlideOp *pso
}
/* common code for defining RNA properties */
+/* TODO: Skip save on these? */
static void pose_slide_opdef_properties(wmOperatorType *ot)
{
+ RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for which keyframe is favored more", 0.3, 0.7);
+
RNA_def_int(ot->srna, "prev_frame", 0, MINAFRAME, MAXFRAME, "Previous Keyframe", "Frame number of keyframe immediately before the current frame", 0, 50);
RNA_def_int(ot->srna, "next_frame", 0, MINAFRAME, MAXFRAME, "Next Keyframe", "Frame number of keyframe immediately after the current frame", 0, 50);
- RNA_def_float_percentage(ot->srna, "percentage", 0.5f, 0.0f, 1.0f, "Percentage", "Weighting factor for the sliding operation", 0.3, 0.7);
+
+ RNA_def_enum(ot->srna, "channels", prop_channels_types, PS_TFM_ALL, "Channels", "Set of properties that are affected");
+ RNA_def_enum(ot->srna, "axis_lock", prop_axis_lock_types, 0, "Axis Lock", "Transform axis to restrict effects to");
}
/* ------------------------------------ */
diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c
index 661a8e1de9f..d8bef20b118 100644
--- a/source/blender/editors/armature/reeb.c
+++ b/source/blender/editors/armature/reeb.c
@@ -3199,237 +3199,3 @@ ReebGraph *BIF_ReebGraphMultiFromEditMesh(bContext *C)
return rg;
#endif
}
-
-#if 0
-
-ReebGraph *BIF_ReebGraphFromEditMesh(void)
-{
- EditMesh *em = G.editMesh;
- EdgeIndex indexed_edges;
- VertexData *data;
- ReebGraph *rg = NULL;
-
- if (em == NULL)
- return NULL;
-
- data = allocVertexData(em);
-
- buildIndexedEdges(em, &indexed_edges);
-
- if (weightFromDistance(em, &indexed_edges) == 0)
- {
- error("No selected vertex\n");
- freeEdgeIndex(&indexed_edges);
- freeEdgeIndex(&indexed_edges);
- return NULL;
- }
-
- renormalizeWeight(em, 1.0f);
-
- if (G.scene->toolsettings->skgen_options & SKGEN_HARMONIC)
- {
- weightToHarmonic(em, &indexed_edges);
- }
-
- freeEdgeIndex(&indexed_edges);
-
-#ifdef DEBUG_REEB
-// weightToVCol(em, 1);
-#endif
-
- rg = generateReebGraph(em, G.scene->toolsettings->skgen_resolution);
-
-
- /* Remove arcs without embedding */
- filterNullReebGraph(rg);
-
- /* smart filter and loop filter on basic level */
- filterGraph(rg, SKGEN_FILTER_SMART, 0, 0);
-
- repositionNodes(rg);
-
- /* Filtering might have created degree 2 nodes, so remove them */
- removeNormalNodes(rg);
-
- joinSubgraphs(rg, 1.0);
-
- BLI_buildAdjacencyList((BGraph *)rg);
-
- /* calc length before copy, so we have same length on all levels */
- BLI_calcGraphLength((BGraph *)rg);
-
- filterGraph(rg, G.scene->toolsettings->skgen_options, G.scene->toolsettings->skgen_threshold_internal, G.scene->toolsettings->skgen_threshold_external);
-
- finalizeGraph(rg, G.scene->toolsettings->skgen_postpro_passes, G.scene->toolsettings->skgen_postpro);
-
-#ifdef DEBUG_REEB
- REEB_exportGraph(rg, -1);
-
- arcToVCol(rg, em, 0);
- //angleToVCol(em, 1);
-#endif
-
- printf("DONE\n");
- printf("%i subgraphs\n", BLI_FlagSubgraphs((BGraph *)rg));
-
- MEM_freeN(data);
-
- return rg;
-}
-
-void BIF_GlobalReebFree()
-{
- if (GLOBAL_RG != NULL)
- {
- REEB_freeGraph(GLOBAL_RG);
- GLOBAL_RG = NULL;
- }
-}
-
-void BIF_GlobalReebGraphFromEditMesh(void)
-{
- ReebGraph *rg;
-
- BIF_GlobalReebFree();
-
- rg = BIF_ReebGraphMultiFromEditMesh();
-
- GLOBAL_RG = rg;
-}
-
-void REEB_draw()
-{
- ReebGraph *rg;
- ReebArc *arc;
- int i = 0;
-
- if (GLOBAL_RG == NULL)
- {
- return;
- }
-
- if (GLOBAL_RG->link_up && G.scene->toolsettings->skgen_options & SKGEN_DISP_ORIG)
- {
- for (rg = GLOBAL_RG; rg->link_up; rg = rg->link_up) ;
- }
- else {
- i = G.scene->toolsettings->skgen_multi_level;
-
- for (rg = GLOBAL_RG; rg->multi_level != i && rg->link_up; rg = rg->link_up) ;
- }
-
- glPointSize(BIF_GetThemeValuef(TH_VERTEX_SIZE));
-
- glDisable(GL_DEPTH_TEST);
- for (arc = rg->arcs.first; arc; arc = arc->next, i++)
- {
- ReebArcIterator arc_iter;
- BArcIterator *iter = (BArcIterator *)&arc_iter;
- float vec[3];
- char text[128];
- char *s = text;
-
- glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE) + 2);
- glColor3f(0, 0, 0);
- glBegin(GL_LINE_STRIP);
- glVertex3fv(arc->head->p);
-
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (IT_next(iter); IT_stopped(iter) == 0; IT_next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
-
- glVertex3fv(arc->tail->p);
- glEnd();
-
- glLineWidth(BIF_GetThemeValuef(TH_VERTEX_SIZE));
-
- if (arc->symmetry_level == 1)
- {
- glColor3f(1, 0, 0);
- }
- else if (arc->symmetry_flag == SYM_SIDE_POSITIVE || arc->symmetry_flag == SYM_SIDE_NEGATIVE)
- {
- glColor3f(1, 0.5f, 0);
- }
- else if (arc->symmetry_flag >= SYM_SIDE_RADIAL)
- {
- glColor3f(0.5f, 1, 0);
- }
- else {
- glColor3f(1, 1, 0);
- }
- glBegin(GL_LINE_STRIP);
- glVertex3fv(arc->head->p);
-
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
-
- glVertex3fv(arc->tail->p);
- glEnd();
-
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_EMBED)
- {
- glColor3f(1, 1, 1);
- glBegin(GL_POINTS);
- glVertex3fv(arc->head->p);
- glVertex3fv(arc->tail->p);
-
- glColor3f(0.5f, 0.5f, 1);
- if (arc->bcount)
- {
- initArcIterator(iter, arc, arc->head);
- for (iter->next(iter); IT_stopped(iter) == 0; iter->next(iter))
- {
- glVertex3fv(iter->p);
- }
- }
- glEnd();
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
- {
- mid_v3_v3v3(vec, arc->head->p, arc->tail->p);
- s += sprintf(s, "%i (%i-%i-%i) ", i, arc->symmetry_level, arc->symmetry_flag, arc->symmetry_group);
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_WEIGHT)
- {
- s += sprintf(s, "w:%0.3f ", arc->tail->weight - arc->head->weight);
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_LENGTH)
- {
- s += sprintf(s, "l:%0.3f", arc->length);
- }
-
- glColor3f(0, 1, 0);
- glRasterPos3fv(vec);
- BMF_DrawString(G.fonts, text);
- }
-
- if (G.scene->toolsettings->skgen_options & SKGEN_DISP_INDEX)
- {
- sprintf(text, " %i", arc->head->index);
- glRasterPos3fv(arc->head->p);
- BMF_DrawString(G.fonts, text);
-
- sprintf(text, " %i", arc->tail->index);
- glRasterPos3fv(arc->tail->p);
- BMF_DrawString(G.fonts, text);
- }
- }
- glEnable(GL_DEPTH_TEST);
-}
-
-#endif
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 6b5a5d81d32..f6528658490 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -92,14 +92,6 @@ typedef struct {
int flag;
} UndoCurve;
-/* Definitions needed for shape keys */
-typedef struct {
- void *orig_cv;
- int key_index, nu_index, pt_index, vertex_index;
- bool switched;
- Nurb *orig_nu;
-} CVKeyIndex;
-
void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus);
static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split);
static int curve_delete_segments(Object *obedit, const bool split);
@@ -139,9 +131,9 @@ void printknots(Object *obedit)
/* ********************* Shape keys *************** */
-static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index, Nurb *orig_nu)
+static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt_index, int vertex_index)
{
- CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), "init_cvKeyIndex");
+ CVKeyIndex *cvIndex = MEM_callocN(sizeof(CVKeyIndex), __func__);
cvIndex->orig_cv = cv;
cvIndex->key_index = key_index;
@@ -149,7 +141,6 @@ static CVKeyIndex *init_cvKeyIndex(void *cv, int key_index, int nu_index, int pt
cvIndex->pt_index = pt_index;
cvIndex->vertex_index = vertex_index;
cvIndex->switched = false;
- cvIndex->orig_nu = orig_nu;
return cvIndex;
}
@@ -175,7 +166,12 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
origbezt = orignu->bezt;
pt_index = 0;
while (a--) {
- keyIndex = init_cvKeyIndex(origbezt, key_index, nu_index, pt_index, vertex_index, orignu);
+ /* We cannot keep *any* reference to curve obdata,
+ * it might be replaced and freed while editcurve remain in use (in viewport render case e.g.).
+ * Note that we could use a pool to avoid lots of malloc's here, but... not really a problem for now. */
+ BezTriple *origbezt_cpy = MEM_mallocN(sizeof(*origbezt), __func__);
+ *origbezt_cpy = *origbezt;
+ keyIndex = init_cvKeyIndex(origbezt_cpy, key_index, nu_index, pt_index, vertex_index);
BLI_ghash_insert(gh, bezt, keyIndex);
key_index += 12;
vertex_index += 3;
@@ -190,7 +186,12 @@ static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
origbp = orignu->bp;
pt_index = 0;
while (a--) {
- keyIndex = init_cvKeyIndex(origbp, key_index, nu_index, pt_index, vertex_index, orignu);
+ /* We cannot keep *any* reference to curve obdata,
+ * it might be replaced and freed while editcurve remain in use (in viewport render case e.g.).
+ * Note that we could use a pool to avoid lots of malloc's here, but... not really a problem for now. */
+ BPoint *origbp_cpy = MEM_mallocN(sizeof(*origbp_cpy), __func__);
+ *origbp_cpy = *origbp;
+ keyIndex = init_cvKeyIndex(origbp_cpy, key_index, nu_index, pt_index, vertex_index);
BLI_ghash_insert(gh, bp, keyIndex);
key_index += 4;
bp++;
@@ -251,23 +252,22 @@ static int getKeyIndexOrig_keyIndex(EditNurb *editnurb, void *cv)
return index->key_index;
}
-static void keyIndex_delCV(EditNurb *editnurb, const void *cv)
+static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
{
if (!editnurb->keyindex) {
return;
}
- BLI_ghash_remove(editnurb->keyindex, cv, NULL, MEM_freeN);
-}
-
-static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
-{
- keyIndex_delCV(editnurb, bezt);
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
}
static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
{
- keyIndex_delCV(editnurb, bp);
+ if (!editnurb->keyindex) {
+ return;
+ }
+
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
}
static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
@@ -283,7 +283,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
a = nu->pntsu;
while (a--) {
- BLI_ghash_remove(editnurb->keyindex, bezt, NULL, MEM_freeN);
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bezt);
bezt++;
}
}
@@ -292,7 +292,7 @@ static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
a = nu->pntsu * nu->pntsv;
while (a--) {
- BLI_ghash_remove(editnurb->keyindex, bp, NULL, MEM_freeN);
+ BKE_curve_editNurb_keyIndex_delCV(editnurb->keyindex, bp);
bp++;
}
}
@@ -536,6 +536,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex)
CVKeyIndex *newIndex = MEM_mallocN(sizeof(CVKeyIndex), "dupli_keyIndexHash index");
memcpy(newIndex, index, sizeof(CVKeyIndex));
+ newIndex->orig_cv = MEM_dupallocN(index->orig_cv);
BLI_ghash_insert(gh, cv, newIndex);
}
@@ -625,7 +626,7 @@ static void calc_keyHandles(ListBase *nurb, float *key)
}
}
-static void calc_shapeKeys(Object *obedit)
+static void calc_shapeKeys(Object *obedit, ListBase *newnurbs)
{
Curve *cu = (Curve *)obedit->data;
@@ -637,7 +638,7 @@ static void calc_shapeKeys(Object *obedit)
KeyBlock *actkey = BLI_findlink(&cu->key->block, editnurb->shapenr - 1);
BezTriple *bezt, *oldbezt;
BPoint *bp, *oldbp;
- Nurb *nu;
+ Nurb *nu, *newnu;
int totvert = BKE_nurbList_verts_count(&editnurb->nurbs);
float (*ofs)[3] = NULL;
@@ -707,20 +708,25 @@ static void calc_shapeKeys(Object *obedit)
currkey = cu->key->block.first;
while (currkey) {
- int apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
+ const bool apply_offset = (ofs && (currkey != actkey) && (editnurb->shapenr - 1 == currkey->relative));
float *fp = newkey = MEM_callocN(cu->key->elemsize * totvert, "currkey->data");
ofp = oldkey = currkey->data;
nu = editnurb->nurbs.first;
+ /* We need to restore to original curve into newnurb, *not* editcurve's nurbs.
+ * Otherwise, in case we update obdata *without* leaving editmode (e.g. viewport render), we would
+ * invalidate editcurve. */
+ newnu = newnurbs->first;
i = 0;
while (nu) {
if (currkey == actkey) {
- int restore = actkey != cu->key->refkey;
+ const bool restore = actkey != cu->key->refkey;
if (nu->bezt) {
bezt = nu->bezt;
a = nu->pntsu;
+ BezTriple *newbezt = newnu->bezt;
while (a--) {
int j;
oldbezt = getKeyIndexOrig_bezt(editnurb, bezt);
@@ -729,7 +735,7 @@ static void calc_shapeKeys(Object *obedit)
copy_v3_v3(fp, bezt->vec[j]);
if (restore && oldbezt) {
- copy_v3_v3(bezt->vec[j], oldbezt->vec[j]);
+ copy_v3_v3(newbezt->vec[j], oldbezt->vec[j]);
}
fp += 3;
@@ -737,16 +743,18 @@ static void calc_shapeKeys(Object *obedit)
fp[0] = bezt->alfa;
if (restore && oldbezt) {
- bezt->alfa = oldbezt->alfa;
+ newbezt->alfa = oldbezt->alfa;
}
fp += 3; ++i; /* alphas */
bezt++;
+ newbezt++;
}
}
else {
bp = nu->bp;
a = nu->pntsu * nu->pntsv;
+ BPoint *newbp = newnu->bp;
while (a--) {
oldbp = getKeyIndexOrig_bp(editnurb, bp);
@@ -755,12 +763,13 @@ static void calc_shapeKeys(Object *obedit)
fp[3] = bp->alfa;
if (restore && oldbp) {
- copy_v3_v3(bp->vec, oldbp->vec);
- bp->alfa = oldbp->alfa;
+ copy_v3_v3(newbp->vec, oldbp->vec);
+ newbp->alfa = oldbp->alfa;
}
fp += 4;
bp++;
+ newbp++;
i += 2;
}
}
@@ -1205,9 +1214,13 @@ void ED_curve_editnurb_load(Object *obedit)
}
}
+ /* We have to pass also new copied nurbs, since we want to restore original curve (without edited shapekey)
+ * on obdata, but *not* on editcurve itself (ED_curve_editnurb_load call does not always implies freeing
+ * of editcurve, e.g. when called to generate render data...). */
+ calc_shapeKeys(obedit, &newnurb);
+
cu->nurb = newnurb;
- calc_shapeKeys(obedit);
ED_curve_updateAnimPaths(obedit->data);
BKE_nurbList_free(&oldnurb);
@@ -1228,13 +1241,11 @@ void ED_curve_editnurb_make(Object *obedit)
if (actkey) {
// XXX strcpy(G.editModeTitleExtra, "(Key) ");
undo_editmode_clear();
- BKE_keyblock_convert_to_curve(actkey, cu, &cu->nurb);
}
if (editnurb) {
BKE_nurbList_free(&editnurb->nurbs);
- BKE_curve_editNurb_keyIndex_free(editnurb);
- editnurb->keyindex = NULL;
+ BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
}
else {
editnurb = MEM_callocN(sizeof(EditNurb), "editnurb");
@@ -1249,12 +1260,16 @@ void ED_curve_editnurb_make(Object *obedit)
nu = nu->next;
}
- if (actkey)
- editnurb->shapenr = obedit->shapenr;
-
/* animation could be added in editmode even if there was no animdata in
* object mode hence we always need CVs index be created */
init_editNurb_keyIndex(editnurb, &cu->nurb);
+
+ if (actkey) {
+ editnurb->shapenr = obedit->shapenr;
+ /* Apply shapekey to new nurbs of editnurb, not those of original curve (and *after* we generated keyIndex),
+ * else we do not have valid 'original' data to properly restore curve when leaving editmode. */
+ BKE_keyblock_convert_to_curve(actkey, cu, &editnurb->nurbs);
+ }
}
}
@@ -1311,8 +1326,7 @@ static int separate_exec(bContext *C, wmOperator *op)
ED_curve_editnurb_make(newob);
newedit = newcu->editnurb;
BKE_nurbList_free(&newedit->nurbs);
- BKE_curve_editNurb_keyIndex_free(newedit);
- newedit->keyindex = NULL;
+ BKE_curve_editNurb_keyIndex_free(&newedit->keyindex);
BLI_movelisttolist(&newedit->nurbs, &newnurb);
/* 4. put old object out of editmode and delete separated geometry */
@@ -6112,7 +6126,7 @@ static void undoCurve_to_editCurve(void *ucu, void *UNUSED(edata), void *cu_v)
BKE_nurbList_free(editbase);
if (undoCurve->undoIndex) {
- BLI_ghash_free(editnurb->keyindex, NULL, MEM_freeN);
+ BKE_curve_editNurb_keyIndex_free(&editnurb->keyindex);
editnurb->keyindex = dupli_keyIndexHash(undoCurve->undoIndex);
}
@@ -6190,8 +6204,7 @@ static void free_undoCurve(void *ucv)
BKE_nurbList_free(&undoCurve->nubase);
- if (undoCurve->undoIndex)
- BLI_ghash_free(undoCurve->undoIndex, NULL, MEM_freeN);
+ BKE_curve_editNurb_keyIndex_free(&undoCurve->undoIndex);
free_fcurves(&undoCurve->fcurves);
free_fcurves(&undoCurve->drivers);
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 4720b76342c..cf7cfec5130 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -48,7 +48,9 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "curve_intern.h"
@@ -90,25 +92,17 @@ static float depth_read_zbuf(const ViewContext *vc, int x, int y)
}
static bool depth_unproject(
- const ARegion *ar, const bglMats *mats,
+ const ARegion *ar,
const int mval[2], const double depth,
float r_location_world[3])
{
- double p[3];
- if (gluUnProject(
- (double)ar->winrct.xmin + mval[0] + 0.5,
- (double)ar->winrct.ymin + mval[1] + 0.5,
- depth, mats->modelview, mats->projection, (const GLint *)mats->viewport,
- &p[0], &p[1], &p[2]))
- {
- copy_v3fl_v3db(r_location_world, p);
- return true;
- }
- return false;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
}
static bool depth_read_normal(
- const ViewContext *vc, const bglMats *mats, const int mval[2],
+ const ViewContext *vc, const int mval[2],
float r_normal[3])
{
/* pixels surrounding */
@@ -124,7 +118,7 @@ static bool depth_read_normal(
const double depth = (double)depth_read_zbuf(vc, mval_ofs[0], mval_ofs[1]);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (depth_unproject(ar, mats, mval_ofs, depth, coords[i])) {
+ if (depth_unproject(ar, mval_ofs, depth, coords[i])) {
depths_valid[i] = true;
}
}
@@ -226,7 +220,6 @@ struct CurveDrawData {
} prev;
ViewContext vc;
- bglMats mats;
enum {
CURVE_DRAW_IDLE = 0,
CURVE_DRAW_PAINTING = 1,
@@ -312,7 +305,7 @@ static bool stroke_elem_project(
{
const double depth = (double)depth_read_zbuf(&cdd->vc, mval_i[0], mval_i[1]);
if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (depth_unproject(ar, &cdd->mats, mval_i, depth, r_location_world)) {
+ if (depth_unproject(ar, mval_i, depth, r_location_world)) {
is_location_world_set = true;
if (r_normal_world) {
zero_v3(r_normal_world);
@@ -321,7 +314,7 @@ static bool stroke_elem_project(
if (surface_offset != 0.0f) {
const float offset = cdd->project.use_surface_offset_absolute ? 1.0f : radius;
float normal[3];
- if (depth_read_normal(&cdd->vc, &cdd->mats, mval_i, normal)) {
+ if (depth_read_normal(&cdd->vc, mval_i, normal)) {
madd_v3_v3fl(r_location_world, normal, offset * surface_offset);
if (r_normal_world) {
copy_v3_v3(r_normal_world, normal);
@@ -467,39 +460,43 @@ static void curve_draw_stroke_3d(const struct bContext *UNUSED(C), ARegion *UNUS
Object *obedit = cdd->vc.obedit;
Curve *cu = obedit->data;
- UI_ThemeColor(TH_WIRE);
-
if (cu->ext2 > 0.0f) {
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
-
BLI_mempool_iter iter;
const struct StrokeElem *selem;
const float location_zero[3] = {0};
const float *location_prev = location_zero;
+ float color[3];
+ UI_GetThemeColor3fv(TH_WIRE, color);
+
+ Batch *sphere = Batch_get_sphere(0);
+ Batch_set_builtin_program(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ Batch_Uniform3fv(sphere, "color", color);
+
/* scale to edit-mode space */
- glPushMatrix();
- glMultMatrixf(obedit->obmat);
+ gpuPushMatrix();
+ gpuMultMatrix3D(obedit->obmat);
BLI_mempool_iternew(cdd->stroke_elem_pool, &iter);
for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) {
- glTranslatef(
+ gpuTranslate3f(
selem->location_local[0] - location_prev[0],
selem->location_local[1] - location_prev[1],
selem->location_local[2] - location_prev[2]);
location_prev = selem->location_local;
+
const float radius = stroke_elem_radius(cdd, selem);
- gluSphere(qobj, radius, 12, 8);
+
+ gpuPushMatrix();
+ gpuScaleUniform(radius);
+ Batch_draw(sphere);
+ gpuPopMatrix();
location_prev = selem->location_local;
}
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+ gpuPopMatrix();
}
if (stroke_len > 1) {
@@ -644,7 +641,7 @@ static void curve_draw_event_add_first(wmOperator *op, const wmEvent *event)
CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW,
CURVE_PAINT_SURFACE_PLANE_NORMAL_SURFACE))
{
- if (depth_read_normal(&cdd->vc, &cdd->mats, event->mval, normal)) {
+ if (depth_read_normal(&cdd->vc, event->mval, normal)) {
if (cps->surface_plane == CURVE_PAINT_SURFACE_PLANE_NORMAL_VIEW) {
float cross_a[3], cross_b[3];
cross_v3_v3v3(cross_a, rv3d->viewinv[2], normal);
@@ -1180,8 +1177,6 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if ((cps->depth_mode == CURVE_PAINT_PROJECT_SURFACE) &&
(v3d->drawtype > OB_WIRE))
{
- view3d_get_transformation(cdd->vc.ar, cdd->vc.rv3d, NULL, &cdd->mats);
-
/* needed or else the draw matrix can be incorrect */
view3d_operator_needs_opengl(C);
diff --git a/source/blender/editors/gpencil/drawgpencil.c b/source/blender/editors/gpencil/drawgpencil.c
index 05eb51fb02f..7e37d0a5a83 100644
--- a/source/blender/editors/gpencil/drawgpencil.c
+++ b/source/blender/editors/gpencil/drawgpencil.c
@@ -94,7 +94,9 @@ typedef enum eDrawStrokeFlags {
/* thickness above which we should use special drawing */
+#if 0
#define GP_DRAWTHICKNESS_SPECIAL 3
+#endif
/* conversion utility (float --> normalized unsigned byte) */
#define F2UB(x) (unsigned char)(255.0f * x)
@@ -578,38 +580,6 @@ static void gp_draw_stroke_fill(
immEnd();
immUnbindProgram();
}
-
-#if 0 /* convert to modern GL only if needed */
- else {
- /* As an initial implementation, we use the OpenGL filled polygon drawing
- * here since it's the easiest option to implement for this case. It does
- * come with limitations (notably for concave shapes), though it shouldn't
- * be much of an issue in most cases.
- *
- * We keep this legacy implementation around despite now having the high quality
- * fills, as this is necessary for keeping everything working nicely for files
- * created using old versions of Blender which may have depended on the artifacts
- * the old fills created.
- */
- bGPDspoint *pt = gps->points;
-
- glBegin(GL_POLYGON);
- for (int i = 0; i < gps->totpoints; i++, pt++) {
- if (gps->flag & GP_STROKE_3DSPACE) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- else {
- float co[2];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, gps->flag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- }
-
- glEnd();
- }
-#endif
}
/* ----- Existing Strokes Drawing (3D and Point) ------ */
@@ -629,10 +599,10 @@ static void gp_draw_stroke_point(
unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
if (sflag & GP_STROKE_3DSPACE) {
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
}
else {
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
/* get 2D coordinates of point */
float co[3] = { 0.0f };
@@ -737,29 +707,13 @@ static void gp_draw_stroke_3d(const bGPDspoint *points, int totpoints, short thi
immEnd();
immUnbindProgram();
-
-#if 0 /* convert to modern GL only if needed */
- /* draw debug points of curve on top? */
- /* XXX: for now, we represent "selected" strokes in the same way as debug, which isn't used anymore */
- if (debug) {
- glPointSize((float)(thickness + 2));
-
- glBegin(GL_POINTS);
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints; i++, pt++) {
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- glVertex3fv(fpt);
- }
- glEnd();
- }
-#endif
}
/* ----- Fancy 2D-Stroke Drawing ------ */
/* draw a given stroke in 2d */
static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thickness_s, short dflag, short sflag,
- bool debug, int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
+ bool UNUSED(debug), int offsx, int offsy, int winx, int winy, const float diff_mat[4][4], const float ink[4])
{
/* otherwise thickness is twice that of the 3D view */
float thickness = (float)thickness_s * 0.5f;
@@ -785,7 +739,6 @@ static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thi
unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
- /* this code previously used glShadeModel(GL_FLAT) */
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GL_QUADS, (totpoints - 2) * 4 + 12);
@@ -933,26 +886,6 @@ static void gp_draw_stroke_2d(const bGPDspoint *points, int totpoints, short thi
immEnd();
immUnbindProgram();
}
-
-#if 0 /* convert to modern GL only if needed */
- /* draw debug points of curve on top? (original stroke points) */
- if (debug) {
- glPointSize((float)(thickness_s + 2));
-
- glBegin(GL_POINTS);
- const bGPDspoint *pt = points;
- for (int i = 0; i < totpoints && pt; i++, pt++) {
- float fpt[3];
- float co[2];
- mul_v3_m4v3(fpt, diff_mat, &pt->x);
- gp_calc_2d_stroke_fxy(fpt, sflag, offsx, offsy, winx, winy, co);
- glVertex2fv(co);
- }
- glEnd();
- }
-#else
- UNUSED_VARS(debug);
-#endif
}
/* ----- Strokes Drawing ------ */
@@ -1035,10 +968,6 @@ static void gp_draw_strokes(
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
bglPolygonOffset(1.0f, 1.0f);
-#if 0
- glEnable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(-1.0f, -1.0f);
-#endif
}
/* 3D Fill */
@@ -1101,10 +1030,6 @@ static void gp_draw_strokes(
glDisable(GL_DEPTH_TEST);
bglPolygonOffset(0.0, 0.0);
-#if 0
- glDisable(GL_POLYGON_OFFSET_LINE);
- glPolygonOffset(0, 0);
-#endif
}
}
else {
@@ -1192,10 +1117,6 @@ static void gp_draw_strokes_edit(
/* first arg is normally rv3d->dist, but this isn't
* available here and seems to work quite well without */
bglPolygonOffset(1.0f, 1.0f);
-#if 0
- glEnable(GL_POLYGON_OFFSET_LINE); /* do we want LINE or POINT here? (merwin) */
- glPolygonOffset(-1.0f, -1.0f);
-#endif
}
}
@@ -1597,11 +1518,6 @@ static void gp_draw_data(
const bGPDbrush *brush, float alpha, bGPdata *gpd,
int offsx, int offsy, int winx, int winy, int cfra, int dflag)
{
-#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
- /* reset line drawing style (in case previous user didn't reset) */
- setlinestyle(0);
-#endif
-
/* turn on smooth lines (i.e. anti-aliasing) */
glEnable(GL_LINE_SMOOTH);
@@ -1620,11 +1536,6 @@ static void gp_draw_data(
/* turn off alpha blending, then smooth lines */
glDisable(GL_BLEND); // alpha blending
glDisable(GL_LINE_SMOOTH); // smooth lines
-
-#if 0 /* disable to see if really needed. re-enable or delete by Dec 2016 */
- /* restore initial gl conditions */
- glColor4f(0, 0, 0, 1);
-#endif
}
/* if we have strokes for scenes (3d view)/clips (movie clip editor)
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5b011b679a6..601a86b97cb 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -74,7 +74,6 @@
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_view3d.h"
-#include "ED_screen.h"
#include "ED_space_api.h"
#include "gpencil_intern.h"
@@ -953,6 +952,9 @@ static int gp_dissolve_selected_points(bContext *C)
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps) == false)
+ continue;
if (gps->flag & GP_STROKE_SELECT) {
bGPDspoint *pt;
@@ -1165,6 +1167,9 @@ static int gp_delete_selected_points(bContext *C)
/* skip strokes that are invalid for current view */
if (ED_gpencil_stroke_can_use(C, gps) == false)
continue;
+ /* check if the color is editable */
+ if (ED_gpencil_stroke_color_use(gpl, gps) == false)
+ continue;
if (gps->flag & GP_STROKE_SELECT) {
@@ -1204,7 +1209,7 @@ static int gp_delete_exec(bContext *C, wmOperator *op)
case GP_DELETEOP_POINTS: /* selected points (breaks the stroke into segments) */
result = gp_delete_selected_points(C);
break;
-
+
case GP_DELETEOP_FRAME: /* active frame */
result = gp_actframe_delete_exec(C, op);
break;
@@ -2121,10 +2126,10 @@ static int gp_count_subdivision_cuts(bGPDstroke *gps)
int totnewpoints = 0;
for (i = 0, pt = gps->points; i < gps->totpoints && pt; i++, pt++) {
if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < gps->totpoints){
+ if (i + 1 < gps->totpoints) {
if (gps->points[i + 1].flag & GP_SPOINT_SELECT) {
++totnewpoints;
- };
+ }
}
}
}
@@ -2179,7 +2184,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
/* if next point is selected add a half way point */
if (pt->flag & GP_SPOINT_SELECT) {
- if (i + 1 < oldtotpoints){
+ if (i + 1 < oldtotpoints) {
if (temp_points[i + 1].flag & GP_SPOINT_SELECT) {
pt_final = &gps->points[i2];
/* Interpolate all values */
@@ -2191,7 +2196,7 @@ static int gp_stroke_subdivide_exec(bContext *C, wmOperator *op)
pt_final->time = interpf(pt->time, next->time, 0.5f);
pt_final->flag |= GP_SPOINT_SELECT;
++i2;
- };
+ }
}
}
}
diff --git a/source/blender/editors/gpencil/gpencil_interpolate.c b/source/blender/editors/gpencil/gpencil_interpolate.c
index 297058168a0..d2360fea672 100644
--- a/source/blender/editors/gpencil/gpencil_interpolate.c
+++ b/source/blender/editors/gpencil/gpencil_interpolate.c
@@ -86,13 +86,14 @@
/* Core/Shared Utilities */
/* Poll callback for interpolation operators */
-static int gpencil_interpolate_poll(bContext *C)
+static int gpencil_view3d_poll(bContext *C)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
/* only 3D view */
- if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype != SPACE_VIEW3D) {
return 0;
}
@@ -673,7 +674,7 @@ void GPENCIL_OT_interpolate(wmOperatorType *ot)
ot->invoke = gpencil_interpolate_invoke;
ot->modal = gpencil_interpolate_modal;
ot->cancel = gpencil_interpolate_cancel;
- ot->poll = gpencil_interpolate_poll;
+ ot->poll = gpencil_view3d_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING;
@@ -1017,7 +1018,7 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
/* api callbacks */
ot->exec = gpencil_interpolate_seq_exec;
- ot->poll = gpencil_interpolate_poll;
+ ot->poll = gpencil_view3d_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1025,24 +1026,14 @@ void GPENCIL_OT_interpolate_sequence(wmOperatorType *ot)
/* ******************** Remove Breakdowns ************************ */
-/* Same as gpencil_interpolate_poll(),
- * except we ALSO need to have an active frame that is a breakdown
- */
static int gpencil_interpolate_reverse_poll(bContext *C)
{
- bGPdata *gpd = CTX_data_gpencil_data(C);
- bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
-
- /* only 3D view */
- if (CTX_wm_area(C)->spacetype != SPACE_VIEW3D) {
- return 0;
- }
-
- /* need data to interpolate */
- if (ELEM(NULL, gpd, gpl)) {
+ if (!gpencil_view3d_poll(C)) {
return 0;
}
-
+
+ bGPDlayer *gpl = CTX_data_active_gpencil_layer(C);
+
/* need to be on a breakdown frame */
if ((gpl->actframe == NULL) || (gpl->actframe->key_type != BEZT_KEYTYPE_BREAKDOWN)) {
CTX_wm_operator_poll_msg_set(C, "Expected current frame to be a breakdown");
diff --git a/source/blender/editors/include/BIF_gl.h b/source/blender/editors/include/BIF_gl.h
index e264d9e16a3..3db9cc8c953 100644
--- a/source/blender/editors/include/BIF_gl.h
+++ b/source/blender/editors/include/BIF_gl.h
@@ -48,33 +48,6 @@
* */
void cpack(unsigned int x);
-#ifdef WITH_GL_PROFILE_COMPAT
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-# define glMultMatrixf(x) \
- glMultMatrixf(_Generic((x), \
- float *: (float *)(x), \
- float [16]: (float *)(x), \
- float (*)[4]: (float *)(x), \
- float [4][4]: (float *)(x), \
- const float *: (float *)(x), \
- const float [16]: (float *)(x), \
- const float (*)[4]: (float *)(x), \
- const float [4][4]: (float *)(x)) \
-)
-# define glLoadMatrixf(x) \
- glLoadMatrixf(_Generic((x), \
- float *: (float *)(x), \
- float [16]: (float *)(x), \
- float (*)[4]: (float *)(x), \
- float [4][4]: (float *)(x)) \
-)
-#else
-# define glMultMatrixf(x) glMultMatrixf((float *)(x))
-# define glLoadMatrixf(x) glLoadMatrixf((float *)(x))
-#endif /* C11 */
-#endif /* WITH_GL_PROFILE_COMPAT */
-
-
/* hacking pointsize and linewidth */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define glPointSize(f) glPointSize(U.pixelsize * _Generic((f), double: (float)(f), default: (f)))
@@ -86,19 +59,5 @@ void cpack(unsigned int x);
#define GLA_PIXEL_OFS 0.375f
-
-BLI_INLINE void glTranslate3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
-BLI_INLINE void glTranslate2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
-BLI_INLINE void glTranslate3fv(const float vec[3]) { glTranslatef(UNPACK3(vec)); }
-BLI_INLINE void glTranslate2fv(const float vec[2]) { glTranslatef(UNPACK2(vec), 0.0f); }
-
-BLI_INLINE void glScale3iv(const int vec[3]) { glTranslatef(UNPACK3_EX((const float), vec, )); }
-BLI_INLINE void glScale2iv(const int vec[2]) { glTranslatef(UNPACK2_EX((const float), vec, ), 0.0f); }
-BLI_INLINE void glScale3fv(const float vec[3]) { glScalef(UNPACK3(vec)); }
-BLI_INLINE void glScale2fv(const float vec[2]) { glScalef(UNPACK2(vec), 0.0); }
-
-/* v2 versions don't make much sense for rotation */
-BLI_INLINE void glRotate3fv(const float angle, const float vec[3]) { glRotatef(angle, UNPACK3(vec)); }
-
#endif /* #ifdef __BIF_GL_H__ */
diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 87086addf52..801b90d33d1 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -38,7 +38,7 @@ struct bContext;
struct ColorManagedViewSettings;
struct ColorManagedDisplaySettings;
-/* Several functions defined here are being DEPRECATED for Blender 2.8
+/* A few functions defined here are being DEPRECATED for Blender 2.8
*
* Do not use them in new code, and you are encouraged to
* convert existing code to draw without these.
@@ -47,47 +47,6 @@ struct ColorManagedDisplaySettings;
* - merwin
*/
-void fdrawline(float x1, float y1, float x2, float y2); /* DEPRECATED */
-void fdrawbox(float x1, float y1, float x2, float y2); /* DEPRECATED */
-void fdrawbox_filled(float x1, float y1, float x2, float y2);
-void sdrawline(int x1, int y1, int x2, int y2); /* DEPRECATED */
-void sdrawbox(int x1, int y1, int x2, int y2); /* DEPRECATED */
-
-void fdrawcheckerboard(float x1, float y1, float x2, float y2); /* DEPRECATED */
-
-/* OpenGL stipple defines */
-extern const unsigned char stipple_halftone[128];
-extern const unsigned char stipple_quarttone[128];
-extern const unsigned char stipple_diag_stripes_pos[128];
-extern const unsigned char stipple_diag_stripes_neg[128];
-extern const unsigned char stipple_checker_8px[128];
-
-/**
- * Draw a lined (non-looping) arc with the given
- * \a radius, starting at angle \a start and arcing
- * through \a angle. The arc is centered at the origin
- * and drawn in the XY plane.
- *
- * \param start The initial angle (in radians).
- * \param angle The length of the arc (in radians).
- * \param radius The arc radius.
- * \param nsegments The number of segments to use in drawing the arc.
- */
-void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments); /* DEPRECATED */
-
-/**
- * Draw a filled arc with the given \a radius,
- * starting at angle \a start and arcing through
- * \a angle. The arc is centered at the origin
- * and drawn in the XY plane.
- *
- * \param start The initial angle (in radians).
- * \param angle The length of the arc (in radians).
- * \param radius The arc radius.
- * \param nsegments The number of segments to use in drawing the arc.
- */
-void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments); /* DEPRECATED */
-
/**
* Draw a circle outline with the given \a radius.
* The circle is centered at \a x, \a y and drawn in the XY plane.
@@ -130,6 +89,25 @@ void imm_draw_filled_arc_3D(unsigned int pos, float start, float angle, float ra
void imm_draw_filled_circle(unsigned pos, float x, float y, float radius, int nsegments);
/**
+ * Draw a filled arc with the given inner and outer radius.
+ * The circle is centered at \a x, \a y and drawn in the XY plane.
+ *
+ * \note Arguments are `gluPartialDisk` compatible.
+ *
+ * \param pos: The vertex attribute number for position.
+ * \param x: Horizontal center.
+ * \param y: Vertical center.
+ * \param radius_inner: The inner circle's radius.
+ * \param radius_outer: The outer circle's radius (can be zero).
+ * \param nsegments: The number of segments to use in drawing (more = smoother).
+ * \param start: Specifies the starting angle, in degrees, of the disk portion.
+ * \param sweep: Specifies the sweep angle, in degrees, of the disk portion.
+ */
+void imm_draw_filled_disk_partial(
+ unsigned pos, float x, float y,
+ float radius_inner, float radius_outer, int nsegments, float start, float sweep);
+
+/**
* Draw a lined box.
*
* \param pos The vertex attribute number for position.
@@ -143,7 +121,9 @@ void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2);
/* use this version when VertexFormat has a vec3 position */
void imm_draw_line_box_3D(unsigned pos, float x1, float y1, float x2, float y2);
-void imm_draw_line(unsigned pos, float x1, float y1, float x2, float y2);
+/* Draw a standard checkerboard to indicate transparent backgrounds */
+void imm_draw_checker_box(float x1, float y1, float x2, float y2);
+
/**
* Pack color into 3 bytes
*
@@ -152,6 +132,22 @@ void imm_draw_line(unsigned pos, float x1, float y1, float x2, float y2);
void imm_cpack(unsigned int x);
/**
+* Draw a cylinder. Replacement for gluCylinder.
+* _warning_ : Slow, better use it only if you no other choices.
+*
+* \param pos The vertex attribute number for position.
+* \param nor The vertex attribute number for normal.
+* \param base Specifies the radius of the cylinder at z = 0.
+* \param top Specifies the radius of the cylinder at z = height.
+* \param height Specifies the height of the cylinder.
+* \param slices Specifies the number of subdivisions around the z axis.
+* \param stacks Specifies the number of subdivisions along the z axis.
+*/
+void imm_cylinder_nor(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks);
+void imm_cylinder_wire(unsigned int pos, float base, float top, float height, int slices, int stacks);
+void imm_cylinder(unsigned int pos, float base, float top, float height, int slices, int stacks);
+
+/**
* Returns a float value as obtained by glGetFloatv.
* The param must cause only one value to be gotten from GL.
*/
@@ -171,43 +167,10 @@ int glaGetOneInt(int param);
*/
void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y);
-/**
- * Functions like a limited glDrawPixels, except ensures that
- * the image is displayed onscreen even if the \a x and \a y
- * coordinates for would be clipped. The routine respects the
- * glPixelZoom values, pixel unpacking parameters are _not_
- * respected.
- *
- * \attention This routine makes many assumptions: the rect data
- * is expected to be in RGBA unsigned byte format, the coordinate
- * (GLA_PIXEL_OFS, GLA_PIXEL_OFS) is assumed to be within the view frustum,
- * and the modelview and projection matrices are assumed to define a
- * 1-to-1 mapping to screen space.
- * \attention Furthermore, in the case of zoomed or unpixel aligned
- * images extending outside the view frustum, but still within the
- * window, some portion of the image may be visible left and/or
- * below of the given \a x and \a y coordinates. It is recommended
- * to use the glScissor functionality if images are to be drawn
- * with an inset view matrix.
- */
-void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect);
-
-/**
- * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
- * image using textures, which can be tremendously faster on low-end
- * cards, and also avoids problems with the raster position being
- * clipped when offscreen. The routine respects the glPixelZoom values,
- * pixel unpacking parameters are _not_ respected.
- *
- * \attention This routine makes many assumptions: the rect data
- * is expected to be in RGBA byte or float format, and the
- * modelview and projection matrices are assumed to define a
- * 1-to-1 mapping to screen space.
- */
-
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
-void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
+/* To be used before calling immDrawPixelsTex
+ * Default shader is GPU_SHADER_2D_IMAGE_COLOR
+ * Returns a shader to be able to set uniforms */
+struct GPUShader *immDrawPixelsTexSetup(int builtin);
/**
* immDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the
@@ -216,6 +179,8 @@ void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int forma
* clipped when offscreen. Pixel unpacking parameters and
* the glPixelZoom values are _not_ respected.
*
+ * \attention Use immDrawPixelsTexSetup before calling this function.
+ *
* \attention This routine makes many assumptions: the rect data
* is expected to be in RGBA byte or float format, and the
* modelview and projection matrices are assumed to define a
@@ -226,21 +191,6 @@ void immDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int ty
void immDrawPixelsTex_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y,
float xzoom, float yzoom, float color[4]);
-
-/**
- * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef.
- * only RGBA
- * needs glaDefine2DArea to be set.
- */
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect);
-void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
-
-
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY);
-void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y);
-
void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
float xzoom, float yzoom, float color[4]);
void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY,
@@ -261,6 +211,8 @@ void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h, int
*/
void glaDefine2DArea(struct rcti *screen_rect);
+/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
+
#if 0 /* UNUSED */
typedef struct gla2DDrawInfo gla2DDrawInfo;
@@ -283,37 +235,33 @@ void setlinestyle(int nr);
/* own working polygon offset */
void bglPolygonOffset(float viewdist, float dist);
-/* For caching opengl matrices (gluProject/gluUnProject) */
-typedef struct bglMats {
- double modelview[16];
- double projection[16];
- int viewport[4];
-} bglMats;
-void bgl_get_mats(bglMats *mats);
-
/* **** Color management helper functions for GLSL display/transform ***** */
/* Draw imbuf on a screen, preferably using GLSL display transform */
void glaDrawImBuf_glsl(struct ImBuf *ibuf, float x, float y, int zoomfilter,
struct ColorManagedViewSettings *view_settings,
- struct ColorManagedDisplaySettings *display_settings);
+ struct ColorManagedDisplaySettings *display_settings,
+ float zoom_x, float zoom_y);
void glaDrawImBuf_glsl_clipping(struct ImBuf *ibuf, float x, float y, int zoomfilter,
struct ColorManagedViewSettings *view_settings,
struct ColorManagedDisplaySettings *display_settings,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y);
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y);
/* Draw imbuf on a screen, preferably using GLSL display transform */
-void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter);
+void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter,
+ float zoom_x, float zoom_y);
void glaDrawImBuf_glsl_ctx_clipping(const struct bContext *C,
struct ImBuf *ibuf,
float x, float y,
int zoomfilter,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y);
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y);
-void glaDrawBorderCorners(const struct rcti *border, float zoomx, float zoomy);
+void immDrawBorderCorners(unsigned int pos, const struct rcti *border, float zoomx, float zoomy);
#endif /* __BIF_GLUTIL_H__ */
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 4a4ab832b28..a65c6eec6ae 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -82,6 +82,7 @@ typedef struct bAnimContext {
struct bDopeSheet *ads; /* dopesheet data for editor (or which is being used) */
struct Scene *scene; /* active scene */
+ struct SceneLayer *scene_layer; /* active scene layer */
struct Object *obact; /* active object */
ListBase *markers; /* active set of markers */
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 3bde01a1bdd..7866bed8666 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -47,6 +47,7 @@ struct Object;
struct Base;
struct ReportList;
struct Scene;
+struct SceneLayer;
struct ViewContext;
struct wmKeyConfig;
struct wmOperator;
@@ -83,6 +84,12 @@ typedef struct EditBone {
short segments;
+ /* Used for display */
+ float disp_mat[4][4]; /* in Armature space, rest pos matrix */
+ float disp_tail_mat[4][4]; /* in Armature space, rest pos matrix */
+ /* 32 == MAX_BBONE_SUBDIV */
+ float disp_bbone_mat[32][4][4]; /* in Armature space, rest pos matrix */
+
/* Used to store temporary data */
union {
struct EditBone *ebone;
@@ -131,8 +138,9 @@ void ED_armature_ebone_listbase_temp_clear(struct ListBase *lb);
void ED_armature_deselect_all(struct Object *obedit);
void ED_armature_deselect_all_visible(struct Object *obedit);
-int ED_do_pose_selectbuffer(struct Scene *scene, struct BaseLegacy *base, unsigned int *buffer,
- short hits, bool extend, bool deselect, bool toggle, bool do_nearest);
+bool ED_do_pose_selectbuffer(
+ struct Scene *scene, struct SceneLayer *sl, struct Base *base, const unsigned int *buffer, short hits,
+ bool extend, bool deselect, bool toggle, bool do_nearest);
bool ED_armature_select_pick(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
int join_armature_exec(struct bContext *C, struct wmOperator *op);
struct Bone *get_indexed_bone(struct Object *ob, int index);
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index 283113f93d6..26d456b03d6 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -39,6 +39,7 @@ struct ToolSettings;
struct wmWindowManager;
struct ARegion;
struct Scene;
+struct SceneLayer;
/* image_edit.c, exported for transform */
struct Image *ED_space_image(struct SpaceImage *sima);
@@ -74,7 +75,7 @@ bool ED_space_image_show_uvedit(struct SpaceImage *sima, struct Object *obedit);
bool ED_space_image_paint_curve(const struct bContext *C);
-bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima);
+bool ED_space_image_check_show_maskedit(struct SceneLayer *sl, struct SpaceImage *sima);
int ED_space_image_maskedit_poll(struct bContext *C);
int ED_space_image_maskedit_mask_poll(struct bContext *C);
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 4d79a42e64e..f621ee7989d 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -55,7 +55,6 @@ struct wmOperatorType;
struct PointerRNA;
struct PropertyRNA;
struct EnumPropertyItem;
-struct LayerTree;
/* object_edit.c */
struct Object *ED_object_context(struct bContext *C); /* context.object */
diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h
index 6cb8c0cfb19..41c746aa421 100644
--- a/source/blender/editors/include/ED_particle.h
+++ b/source/blender/editors/include/ED_particle.h
@@ -38,21 +38,22 @@ struct ParticleEditSettings;
struct rcti;
struct PTCacheEdit;
struct Scene;
+struct SceneLayer;
/* particle edit mode */
void PE_free_ptcache_edit(struct PTCacheEdit *edit);
int PE_start_edit(struct PTCacheEdit *edit);
/* access */
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob);
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct SceneLayer *sl, struct Object *ob);
struct PTCacheEdit *PE_create_current(struct Scene *scene, struct Object *ob);
void PE_current_changed(struct Scene *scene, struct Object *ob);
-int PE_minmax(struct Scene *scene, float min[3], float max[3]);
+int PE_minmax(struct Scene *scene, struct SceneLayer *sl, float min[3], float max[3]);
struct ParticleEditSettings *PE_settings(struct Scene *scene);
/* update calls */
void PE_hide_keys_time(struct Scene *scene, struct PTCacheEdit *edit, float cfra);
-void PE_update_object(struct Scene *scene, struct Object *ob, int useflag);
+void PE_update_object(struct Scene *scene, struct SceneLayer *sl, struct Object *ob, int useflag);
/* selection tools */
int PE_mouse_particles(struct bContext *C, const int mval[2], bool extend, bool deselect, bool toggle);
@@ -62,13 +63,13 @@ int PE_lasso_select(struct bContext *C, const int mcords[][2], const short moves
void PE_deselect_all_visible(struct PTCacheEdit *edit);
/* undo */
-void PE_undo_push(struct Scene *scene, const char *str);
-void PE_undo_step(struct Scene *scene, int step);
-void PE_undo(struct Scene *scene);
-void PE_redo(struct Scene *scene);
-bool PE_undo_is_valid(struct Scene *scene);
-void PE_undo_number(struct Scene *scene, int nr);
-const char *PE_undo_get_name(struct Scene *scene, int nr, bool *r_active);
+void PE_undo_push(struct Scene *scene, struct SceneLayer *sl, const char *str);
+void PE_undo_step(struct Scene *scene, struct SceneLayer *sl, int step);
+void PE_undo(struct Scene *scene, struct SceneLayer *sl);
+void PE_redo(struct Scene *scene, struct SceneLayer *sl);
+bool PE_undo_is_valid(struct Scene *scene, struct SceneLayer *sl);
+void PE_undo_number(struct Scene *scene, struct SceneLayer *sl, int nr);
+const char *PE_undo_get_name(struct Scene *scene, struct SceneLayer *sl, int nr, bool *r_active);
#endif /* __ED_PARTICLE_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 01be63919be..f5f66a07aea 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -162,7 +162,6 @@ int ED_operator_image_active(struct bContext *C);
int ED_operator_nla_active(struct bContext *C);
int ED_operator_logic_active(struct bContext *C);
int ED_operator_info_active(struct bContext *C);
-int ED_operator_collections_active(struct bContext *C);
int ED_operator_console_active(struct bContext *C);
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 6daaac5bb42..a81d63d9f25 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -39,8 +39,7 @@ struct rcti;
/* sculpt.c */
void ED_operatortypes_sculpt(void);
-void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar,
- struct RegionView3D *rv3d, struct Object *ob);
+void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *ar, struct Object *ob);
int ED_sculpt_mask_box_select(struct bContext *C, struct ViewContext *vc, const struct rcti *rect, bool select, bool extend);
#endif /* __ED_SCULPT_H__ */
diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h
index b754e1ba20f..d268c578cf2 100644
--- a/source/blender/editors/include/ED_space_api.h
+++ b/source/blender/editors/include/ED_space_api.h
@@ -58,7 +58,6 @@ void ED_spacetype_logic(void);
void ED_spacetype_console(void);
void ED_spacetype_userpref(void);
void ED_spacetype_clip(void);
-void ED_spacetype_collections(void);
/* calls for instancing and freeing spacetype static data
* called in WM_init_exit */
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 535683823bf..e5e8aaa8b3b 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -35,12 +35,14 @@ struct BMesh;
struct BMEditMesh;
struct BMFace;
struct BMLoop;
+struct Depsgraph;
struct Image;
struct ImageUser;
struct MTexPoly;
struct Main;
struct Object;
struct Scene;
+struct SceneLayer;
struct SpaceImage;
struct bNode;
struct wmKeyConfig;
@@ -109,7 +111,7 @@ void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel)
/* uvedit_draw.c */
void ED_image_draw_cursor(struct ARegion *ar, const float cursor[2]);
-void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact);
+void ED_uvedit_draw_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct SceneLayer *sl, struct Object *obedit, struct Object *obact, struct Depsgraph *depsgraph);
/* uvedit_buttons.c */
void ED_uvedit_buttons_register(struct ARegionType *art);
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index cc83b97fc00..319d5afe0f3 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -47,6 +47,7 @@ struct Main;
struct MetaElem;
struct Nurb;
struct Object;
+struct RV3DMatrixStore;
struct RegionView3D;
struct Scene;
struct SceneLayer;
@@ -56,7 +57,6 @@ struct ViewContext;
struct bContext;
struct bPoseChannel;
struct bScreen;
-struct bglMats;
struct rctf;
struct rcti;
struct wmOperator;
@@ -233,7 +233,9 @@ bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, cons
float r_ray_start[3], float r_ray_end[3], const bool do_clip);
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]);
void ED_view3d_ob_project_mat_get_from_obmat(const struct RegionView3D *rv3d, float obmat[4][4], float pmat[4][4]);
-void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z);
+
+void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3]);
+bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3]);
/* end */
@@ -262,7 +264,8 @@ bool ED_view3d_calc_render_border(struct Scene *scene, struct View3D *v3d,
struct ARegion *ar, struct rcti *rect);
void ED_view3d_clipping_calc_from_boundbox(float clip[6][4], const struct BoundBox *clipbb, const bool is_flip);
-void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect);
+void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4],
+ const struct ARegion *ar, const struct Object *ob, const struct rcti *rect);
void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]);
bool ED_view3d_clipping_test(const struct RegionView3D *rv3d, const float co[3], const bool is_local);
void ED_view3d_clipping_set(struct RegionView3D *rv3d);
@@ -278,7 +281,6 @@ float ED_view3d_radius_to_dist(
const char persp, const bool use_aspect,
const float radius);
-void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4]);
void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos);
/* backbuffer select and draw support */
@@ -304,7 +306,22 @@ bool ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], con
/* select */
#define MAXPICKELEMS 2500
#define MAXPICKBUF (4 * MAXPICKELEMS)
-short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, bool do_nearest);
+
+typedef enum {
+ /* all elements in the region, ignore depth */
+ VIEW3D_SELECT_ALL = 0,
+ /* pick also depth sorts (only for small regions!) */
+ VIEW3D_SELECT_PICK_ALL = 1,
+ /* sorts and only returns visible objects (only for small regions!) */
+ VIEW3D_SELECT_PICK_NEAREST = 2,
+} eV3DSelectMode;
+
+void view3d_opengl_select_cache_begin(void);
+void view3d_opengl_select_cache_end(void);
+
+int view3d_opengl_select(
+ struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input,
+ eV3DSelectMode select_mode);
/* view3d_select.c */
float ED_view3d_select_dist_px(void);
@@ -312,7 +329,6 @@ void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc);
void view3d_operator_needs_opengl(const struct bContext *C);
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
-void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats);
/* XXX should move to BLI_math */
bool edge_inside_circle(const float cent[2], float radius, const float screen_co_a[2], const float screen_co_b[2]);
@@ -333,11 +349,11 @@ void ED_view3d_check_mats_rv3d(struct RegionView3D *rv3d);
#endif
int ED_view3d_scene_layer_set(int lay, const int *values, int *active);
-void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt);
+struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d);
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat);
bool ED_view3d_context_activate(struct bContext *C);
-void ED_view3d_draw_offscreen_init(struct Scene *scene, struct View3D *v3d);
+void ED_view3d_draw_offscreen_init(struct Scene *scene, struct SceneLayer *sl, struct View3D *v3d);
void ED_view3d_draw_offscreen(
struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int winx, int winy, float viewmat[4][4],
float winmat[4][4], bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
@@ -345,12 +361,12 @@ void ED_view3d_draw_offscreen(
struct GPUOffScreen *ofs);
struct ImBuf *ED_view3d_draw_offscreen_imbuf(
- struct Scene *scene, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
+ struct Scene *scene, struct SceneLayer *sl, struct View3D *v3d, struct ARegion *ar, int sizex, int sizey,
unsigned int flag, bool draw_background,
int alpha_mode, int samples, bool full_samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
struct ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- struct Scene *scene, struct Object *camera, int width, int height,
+ struct Scene *scene, struct SceneLayer *sl, struct Object *camera, int width, int height,
unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
int alpha_mode, int samples, bool full_samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 8579778ff79..8420591aa3e 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -653,9 +653,9 @@ DEF_ICON(IPO_BACK)
DEF_ICON(IPO_EASE_IN)
DEF_ICON(IPO_EASE_OUT)
DEF_ICON(IPO_EASE_IN_OUT)
+DEF_ICON(NORMALIZE_FCURVES)
#ifndef DEF_ICON_BLANK_SKIP
/* available */
- DEF_ICON(BLANK203)
DEF_ICON(BLANK204)
DEF_ICON(BLANK205)
DEF_ICON(BLANK206)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 153c3d415e6..358df02ea9d 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -212,9 +212,6 @@ enum {
UI_BUT_ALIGN_STITCH_TOP = (1 << 18),
UI_BUT_ALIGN_STITCH_LEFT = (1 << 19),
UI_BUT_ALIGN_ALL = (UI_BUT_ALIGN | UI_BUT_ALIGN_STITCH_TOP | UI_BUT_ALIGN_STITCH_LEFT),
-
- /* Another hack, in some rare cases we don't want any text margin */
- UI_BUT_TEXT_NO_MARGIN = (1 << 20),
};
/* scale fixed button widths by this to account for DPI */
@@ -259,6 +256,7 @@ typedef enum {
UI_BTYPE_CHECKBOX = (13 << 9), /* similar to toggle, display a 'tick' */
UI_BTYPE_CHECKBOX_N = (14 << 9),
UI_BTYPE_COLOR = (15 << 9),
+ UI_BTYPE_TAB = (16 << 9),
UI_BTYPE_SCROLL = (18 << 9),
UI_BTYPE_BLOCK = (19 << 9),
UI_BTYPE_LABEL = (20 << 9),
@@ -426,7 +424,7 @@ typedef void (*uiBlockCancelFunc)(struct bContext *C, void *arg1);
void UI_popup_block_invoke(struct bContext *C, uiBlockCreateFunc func, void *arg);
void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, const char *opname, int opcontext);
-void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg);
+void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, struct wmOperator *op);
/* void uiPupBlockOperator(struct bContext *C, uiBlockCreateFunc func, struct wmOperator *op, int opcontext); */ /* UNUSED */
void UI_popup_block_close(struct bContext *C, struct wmWindow *win, uiBlock *block);
@@ -950,6 +948,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C);
void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C);
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
+void uiTemplateOverrideProperty(uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr, const char *name, const char *custom_template);
void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
void uiTemplateCacheFile(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname);
@@ -1062,7 +1061,7 @@ void UI_fontstyle_draw_simple_backdrop(
int UI_fontstyle_string_width(const struct uiFontStyle *fs, const char *str);
int UI_fontstyle_height_max(const struct uiFontStyle *fs);
-void UI_draw_icon_tri(float x, float y, char dir);
+void UI_draw_icon_tri(float x, float y, char dir, const float[4]);
struct uiStyle *UI_style_get(void); /* use for fonts etc */
struct uiStyle *UI_style_get_dpi(void); /* DPI scaled settings for drawing */
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index f08c46af8a6..cee68ed361c 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -66,6 +66,7 @@ void UI_id_icon_render(
int UI_preview_render_size(enum eIconSizes size);
void UI_icon_draw(float x, float y, int icon_id);
+void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha);
void UI_icon_draw_preview(float x, float y, int icon_id);
void UI_icon_draw_preview_aspect(float x, float y, int icon_id, float aspect);
void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspect, float alpha, int size);
@@ -83,6 +84,5 @@ struct PreviewImage *UI_icon_to_preview(int icon_id);
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big);
int UI_idcode_icon_get(const int idcode);
-int UI_colorset_icon_get(const int set_idx);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 682db20af55..771f9d24e3c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -56,7 +56,7 @@
#include "BKE_screen.h"
#include "BKE_idprop.h"
-#include "BIF_gl.h"
+#include "GPU_matrix.h"
#include "BLF_api.h"
#include "BLT_translation.h"
@@ -499,6 +499,7 @@ static int ui_but_calc_float_precision(uiBut *but, double value)
static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int dashInactiveLines)
{
rcti rect;
+ float color[4] = {1.0f};
if (line->from == NULL || line->to == NULL) return;
@@ -508,15 +509,15 @@ static void ui_draw_linkline(uiLinkLine *line, int highlightActiveLines, int das
rect.ymax = BLI_rctf_cent_y(&line->to->rect);
if (dashInactiveLines)
- UI_ThemeColor(TH_GRID);
+ UI_GetThemeColor4fv(TH_GRID, color);
else if (line->flag & UI_SELECT)
- glColor3ub(100, 100, 100);
+ rgba_float_args_set_ch(color, 100, 100, 100, 255);
else if (highlightActiveLines && ((line->from->flag & UI_ACTIVE) || (line->to->flag & UI_ACTIVE)))
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
else
- glColor3ub(0, 0, 0);
+ rgba_float_args_set_ch(color, 0, 0, 0, 255);
- ui_draw_link_bezier(&rect);
+ ui_draw_link_bezier(&rect, color);
}
static void ui_draw_links(uiBlock *block)
@@ -1337,7 +1338,7 @@ static void ui_but_to_pixelrect(rcti *rect, const ARegion *ar, uiBlock *block, u
rctf rectf;
ui_block_to_window_rctf(ar, block, &rectf, (but) ? &but->rect : &block->rect);
- BLI_rcti_rctf_copy_floor(rect, &rectf);
+ BLI_rcti_rctf_copy(rect, &rectf);
BLI_rcti_translate(rect, -ar->winrct.xmin, -ar->winrct.ymin);
}
@@ -1376,11 +1377,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
ui_but_to_pixelrect(&rect, ar, block, NULL);
/* pixel space for AA widgets */
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ gpuPushMatrix();
+ gpuLoadIdentity();
wmOrtho2_region_pixelspace(ar);
@@ -1404,11 +1402,8 @@ void UI_block_draw(const bContext *C, uiBlock *block)
}
}
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ /* restore model-view matrix */
+ gpuPopMatrix();
if (multisample_enabled)
glEnable(GL_MULTISAMPLE);
@@ -1462,6 +1457,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
UI_GET_BUT_VALUE_INIT(but, *value);
/* support for rna enum buts */
if (but->rnaprop && (RNA_property_flag(but->rnaprop) & PROP_ENUM_FLAG)) {
@@ -2288,7 +2284,7 @@ char *ui_but_string_get_dynamic(uiBut *but, int *r_str_size)
#ifdef WITH_PYTHON
-static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value)
+static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *r_value)
{
char str_unit_convert[256];
const int unit_type = UI_but_unit_type_get(but);
@@ -2300,13 +2296,13 @@ static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char
bUnit_ReplaceString(str_unit_convert, sizeof(str_unit_convert), but->drawstr,
ui_get_but_scale_unit(but, 1.0), but->block->unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type));
- return BPY_execute_string_as_number(C, str_unit_convert, value, true);
+ return BPY_execute_string_as_number(C, str_unit_convert, true, r_value);
}
#endif /* WITH_PYTHON */
-bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *value)
+bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double *r_value)
{
bool ok = false;
@@ -2315,13 +2311,13 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
if (str[0] != '\0') {
bool is_unit_but = (ui_but_is_float(but) && ui_but_is_unit(but));
/* only enable verbose if we won't run again with units */
- if (BPY_execute_string_as_number(C, str, value, is_unit_but == false)) {
+ if (BPY_execute_string_as_number(C, str, is_unit_but == false, r_value)) {
/* if the value parsed ok without unit conversion this button may still need a unit multiplier */
if (is_unit_but) {
char str_new[128];
- BLI_snprintf(str_new, sizeof(str_new), "%f", *value);
- ok = ui_set_but_string_eval_num_unit(C, but, str_new, value);
+ BLI_snprintf(str_new, sizeof(str_new), "%f", *r_value);
+ ok = ui_set_but_string_eval_num_unit(C, but, str_new, r_value);
}
else {
ok = true; /* parse normal string via py (no unit conversion needed) */
@@ -2329,7 +2325,7 @@ bool ui_but_string_set_eval_num(bContext *C, uiBut *but, const char *str, double
}
else if (is_unit_but) {
/* parse failed, this is a unit but so run replacements and parse again */
- ok = ui_set_but_string_eval_num_unit(C, but, str, value);
+ ok = ui_set_but_string_eval_num_unit(C, but, str, r_value);
}
}
@@ -3913,6 +3909,8 @@ uiBut *uiDefIconTextButO_ptr(uiBlock *block, int type, wmOperatorType *ot, int o
uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x, int y, short width, short height, const char *tip)
{
wmOperatorType *ot = WM_operatortype_find(opname, 0);
+ if (str && str[0] == '\0')
+ return uiDefIconButO_ptr(block, type, ot, opcontext, icon, x, y, width, height, tip);
return uiDefIconTextButO_ptr(block, type, ot, opcontext, icon, str, x, y, width, height, tip);
}
@@ -4398,7 +4396,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *but, const c
for (item = item_array; item->identifier; item++) {
/* note: need to give the index rather than the identifier because the enum can be freed */
if (BLI_strcasestr(item->name, str)) {
- if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), 0))
+ if (false == UI_search_item_add(items, item->name, SET_INT_IN_POINTER(item->value), item->icon))
break;
}
}
diff --git a/source/blender/editors/interface/interface_align.c b/source/blender/editors/interface/interface_align.c
index 500744c366d..9aeb685a907 100644
--- a/source/blender/editors/interface/interface_align.c
+++ b/source/blender/editors/interface/interface_align.c
@@ -110,9 +110,9 @@ enum {
bool ui_but_can_align(const uiBut *but)
{
- return (
- !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE) &&
- (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
+ const bool btype_can_align = !ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_CHECKBOX, UI_BTYPE_CHECKBOX_N,
+ UI_BTYPE_TAB, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE);
+ return (btype_can_align && (BLI_rctf_size_x(&but->rect) > 0.0f) && (BLI_rctf_size_y(&but->rect) > 0.0f));
}
/**
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 5da294302e9..a04360b3395 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -39,6 +39,7 @@
#include "BLI_utildefines.h"
#include "BKE_context.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_nla.h"
@@ -210,6 +211,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
/* updates */
driver->flag |= DRIVER_FLAG_RECOMPILE;
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME, NULL);
ok = true;
}
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 7b17c3d6440..6a568567b36 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -50,13 +50,10 @@
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
-#include "GPU_draw.h"
-#include "GPU_basic_shader.h"
#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -467,6 +464,93 @@ void UI_draw_text_underline(int pos_x, int pos_y, int len, int height, const flo
/* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */
+/* based on UI_draw_roundbox_gl_mode, check on making a version which allows us to skip some sides */
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3])
+{
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ /* add a 1px offset, looks nicer */
+ const int minx = rect->xmin + U.pixelsize, maxx = rect->xmax - U.pixelsize;
+ const int miny = rect->ymin + U.pixelsize, maxy = rect->ymax - U.pixelsize;
+ int a;
+ float vec[4][2] = {
+ {0.195, 0.02},
+ {0.55, 0.169},
+ {0.831, 0.45},
+ {0.98, 0.805},
+ };
+
+
+ /* mult */
+ for (a = 0; a < 4; a++) {
+ mul_v2_fl(vec[a], rad);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBeginAtMost(PRIM_LINE_STRIP, 25);
+
+ immAttrib3ubv(col, highlight);
+
+ /* start with corner left-top */
+ if (roundboxtype & UI_CNR_TOP_LEFT) {
+ immVertex2f(pos, minx, maxy - rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + vec[a][1], maxy - rad + vec[a][0]);
+ }
+ immVertex2f(pos, minx + rad, maxy);
+ }
+ else {
+ immVertex2f(pos, minx, maxy);
+ }
+
+ /* corner right-top */
+ if (roundboxtype & UI_CNR_TOP_RIGHT) {
+ immVertex2f(pos, maxx - rad, maxy);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - rad + vec[a][0], maxy - vec[a][1]);
+ }
+ immVertex2f(pos, maxx, maxy - rad);
+ }
+ else {
+ immVertex2f(pos, maxx, maxy);
+ }
+
+ immAttrib3ubv(col, highlight_fade);
+
+ /* corner right-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
+ immVertex2f(pos, maxx, miny + rad);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, maxx - vec[a][1], miny + rad - vec[a][0]);
+ }
+ immVertex2f(pos, maxx - rad, miny);
+ }
+ else {
+ immVertex2f(pos, maxx, miny);
+ }
+
+ /* corner left-bottom */
+ if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
+ immVertex2f(pos, minx + rad, miny);
+ for (a = 0; a < 4; a++) {
+ immVertex2f(pos, minx + rad - vec[a][0], miny + vec[a][1]);
+ }
+ immVertex2f(pos, minx, miny + rad);
+ }
+ else {
+ immVertex2f(pos, minx, miny);
+ }
+
+ immAttrib3ubv(col, highlight);
+
+ /* back to corner left-top */
+ immVertex2f(pos, minx, roundboxtype & UI_CNR_TOP_LEFT ? maxy - rad : maxy);
+
+ immEnd();
+ immUnbindProgram();
+}
+
void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti *rect)
{
#ifdef WITH_HEADLESS
@@ -476,15 +560,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
ImBuf *ibuf = (ImBuf *)but->poin;
if (!ibuf) return;
+
+ float facx = 1.0f;
+ float facy = 1.0f;
int w = BLI_rcti_size_x(rect);
int h = BLI_rcti_size_y(rect);
/* scissor doesn't seem to be doing the right thing...? */
#if 0
- //glColor4f(1.0, 0.f, 0.f, 1.f);
- //fdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax)
-
/* prevent drawing outside widget area */
GLint scissor[4];
glGetIntegerv(GL_SCISSOR_BOX, scissor);
@@ -492,16 +576,15 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w
#endif
glEnable(GL_BLEND);
- glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
if (w != ibuf->x || h != ibuf->y) {
- float facx = (float)w / (float)ibuf->x;
- float facy = (float)h / (float)ibuf->y;
- glPixelZoom(facx, facy);
+ facx = (float)w / (float)ibuf->x;
+ facy = (float)h / (float)ibuf->y;
}
- glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect);
-
- glPixelZoom(1.0f, 1.0f);
+
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect,
+ facx, facy, NULL);
glDisable(GL_BLEND);
@@ -667,8 +750,15 @@ void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol)
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
}
- imm_draw_line(pos, rect.xmin, rect.ymin + fac * h, rect.xmax, rect.ymin + fac * h);
- imm_draw_line(pos, rect.xmin + fac * w, rect.ymin, rect.xmin + fac * w, rect.ymax);
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, rect.xmin, rect.ymin + fac * h);
+ immVertex2f(pos, rect.xmax, rect.ymin + fac * h);
+
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymin);
+ immVertex2f(pos, rect.xmin + fac * w, rect.ymax);
+
+ immEnd();
}
if (hist->mode == HISTO_MODE_LUMA) {
@@ -783,33 +873,63 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
+
/* draw grid lines here */
+ immBegin(GL_LINES, 12);
+
for (int i = 0; i < 6; i++) {
- imm_draw_line(pos, rect.xmin + 22, yofs + (i * 0.2f) * h, rect.xmax + 1, yofs + (i * 0.2f) * h);
+ immVertex2f(pos, rect.xmin + 22, yofs + (i * 0.2f) * h);
+ immVertex2f(pos, rect.xmax + 1, yofs + (i * 0.2f) * h);
}
+
+ immEnd();
+
/* 3 vertical separation */
if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA) {
+ immBegin(GL_LINES, 4);
+
for (int i = 1; i < 3; i++) {
- imm_draw_line(pos, rect.xmin + i * w3, rect.ymin, rect.xmin + i * w3, rect.ymax);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymin);
+ immVertex2f(pos, rect.xmin + i * w3, rect.ymax);
}
+
+ immEnd();
}
/* separate min max zone on the right */
- imm_draw_line(pos, rect.xmin + w, rect.ymin, rect.xmin + w, rect.ymax);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect.xmin + w, rect.ymin);
+ immVertex2f(pos, rect.xmin + w, rect.ymax);
+ immEnd();
+
/* 16-235-240 level in case of ITU-R BT601/709 */
immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709)) {
- imm_draw_line(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
- imm_draw_line(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
- imm_draw_line(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
- imm_draw_line(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+ immBegin(GL_LINES, 8);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 16.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 16.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 22, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + 3 * w3, yofs + h * 235.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 235.0f / 255.0f);
+
+ immVertex2f(pos, rect.xmin + w3, yofs + h * 240.0f / 255.0f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 240.0f / 255.0f);
+
+ immEnd();
}
/* 7.5 IRE black point level for NTSC */
- if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA)
- imm_draw_line(pos, rect.xmin, yofs + h * 0.075f, rect.xmax + 1, yofs + h * 0.075f);
+ if (scopes->wavefrm_mode == SCOPES_WAVEFRM_LUMA) {
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect.xmin, yofs + h * 0.075f);
+ immVertex2f(pos, rect.xmax + 1, yofs + h * 0.075f);
+ immEnd();
+ }
if (scopes->ok && scopes->waveform_1 != NULL) {
- gpuMatrixBegin3D_legacy();
glBlendFunc(GL_ONE, GL_ONE);
glPointSize(1.0);
@@ -818,8 +938,8 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
float col[3] = {alpha, alpha, alpha};
gpuPushMatrix();
- gpuTranslate3f(rect.xmin, yofs, 0.0f);
- gpuScale3f(w, h, 0.0f);
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, col);
@@ -831,13 +951,17 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
max = yofs + scopes->minmax[0][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- imm_draw_line(pos, rect.xmax - 3, min, rect.xmax - 3, max);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect.xmax - 3, min);
+ immVertex2f(pos, rect.xmax - 3, max);
+ immEnd();
}
/* RGB (3 channel) */
else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) {
gpuPushMatrix();
- gpuTranslate3f(rect.xmin, yofs, 0.0f);
- gpuScale3f(w, h, 0.0f);
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w, h);
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, colors_alpha[0]);
waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, colors_alpha[1]);
@@ -856,15 +980,15 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE);
gpuPushMatrix();
- gpuTranslate3f(rect.xmin, yofs, 0.0f);
- gpuScale3f(w3, h, 0.0f);
+ gpuTranslate2f(rect.xmin, yofs);
+ gpuScale2f(w3, h);
waveform_draw_one(scopes->waveform_1, scopes->waveform_tot, (rgb) ? colors_alpha[0] : colorsycc_alpha[0]);
- gpuTranslate3f(1.0f, 0.0f, 0.0f);
+ gpuTranslate2f(1.0f, 0.0f);
waveform_draw_one(scopes->waveform_2, scopes->waveform_tot, (rgb) ? colors_alpha[1] : colorsycc_alpha[1]);
- gpuTranslate3f(1.0f, 0.0f, 0.0f);
+ gpuTranslate2f(1.0f, 0.0f);
waveform_draw_one(scopes->waveform_3, scopes->waveform_tot, (rgb) ? colors_alpha[2] : colorsycc_alpha[2]);
gpuPopMatrix();
@@ -881,10 +1005,13 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol),
max = yofs + scopes->minmax[c][1] * h;
CLAMP(min, rect.ymin, rect.ymax);
CLAMP(max, rect.ymin, rect.ymax);
- imm_draw_line(pos, rect.xmin + w + 2 + c * 2, min, rect.xmin + w + 2 + c * 2, max);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, min);
+ immVertex2f(pos, rect.xmin + w + 2 + c * 2, max);
+ immEnd();
}
}
- gpuMatrixEnd();
}
immUnbindProgram();
@@ -1005,8 +1132,16 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.08f);
/* draw grid elements */
/* cross */
- imm_draw_line(pos, centerx - (diam * 0.5f) - 5, centery, centerx + (diam * 0.5f) + 5, centery);
- imm_draw_line(pos, centerx, centery - (diam * 0.5f) - 5, centerx, centery + (diam * 0.5f) + 5);
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, centerx - (diam * 0.5f) - 5, centery);
+ immVertex2f(pos, centerx + (diam * 0.5f) + 5, centery);
+
+ immVertex2f(pos, centerx, centery - (diam * 0.5f) - 5);
+ immVertex2f(pos, centerx, centery + (diam * 0.5f) + 5);
+
+ immEnd();
+
/* circles */
for (int j = 0; j < 5; j++) {
const int increment = 15;
@@ -1020,8 +1155,12 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
}
/* skin tone line */
immUniformColor4f(1.0f, 0.4f, 0.0f, 0.2f);
- imm_draw_line(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad),
- polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.5f, skin_rad), polar_to_y(centery, diam, 0.5f, skin_rad));
+ immVertex2f(pos, polar_to_x(centerx, diam, 0.1f, skin_rad), polar_to_y(centery, diam, 0.1f, skin_rad));
+ immEnd();
+
/* saturation points */
for (int i = 0; i < 6; i++)
vectorscope_draw_target(pos, centerx, centery, diam, colors[i]);
@@ -1033,15 +1172,13 @@ void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wco
glBlendFunc(GL_ONE, GL_ONE);
glPointSize(1.0);
- gpuMatrixBegin3D_legacy();
gpuPushMatrix();
- gpuTranslate3f(centerx, centery, 0.0f);
- gpuScale3f(diam, diam, 0.0f);
+ gpuTranslate2f(centerx, centery);
+ gpuScaleUniform(diam);
waveform_draw_one(scopes->vecscope, scopes->waveform_tot, col);
gpuPopMatrix();
- gpuMatrixEnd();
}
immUnbindProgram();
@@ -1262,9 +1399,19 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), const rcti
/* layer: box outline */
glEnable(GL_BLEND);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- imm_draw_line(position, x1, y1, x1 + sizex, y1);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(position, x1, y1);
+ immVertex2f(position, x1 + sizex, y1);
+ immEnd();
+
immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- imm_draw_line(position, x1, y1 - 1, x1 + sizex, y1 - 1);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(position, x1, y1 - 1);
+ immVertex2f(position, x1 + sizex, y1 - 1);
+ immEnd();
+
glDisable(GL_BLEND);
/* layer: draw handles */
@@ -1301,10 +1448,8 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
/* setup lights */
ui_but_v3_get(but, light);
- light[2] = -light[2];
/* transform to button */
- gpuMatrixBegin3D_legacy();
gpuPushMatrix();
if (BLI_rcti_size_x(rect) < BLI_rcti_size_y(rect))
@@ -1312,8 +1457,8 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
else
size = 0.5f * BLI_rcti_size_y(rect);
- gpuTranslate3f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect), 0.0f);
- gpuScale3f(size, size, size);
+ gpuTranslate2f(rect->xmin + 0.5f * BLI_rcti_size_x(rect), rect->ymin + 0.5f * BLI_rcti_size_y(rect));
+ gpuScaleUniform(size);
Batch *sphere = Batch_get_sphere(2);
Batch_set_builtin_program(sphere, GPU_SHADER_SIMPLE_LIGHTING);
@@ -1338,7 +1483,6 @@ void ui_draw_but_UNITVEC(uiBut *but, uiWidgetColors *wcol, const rcti *rect)
/* matrix after circle */
gpuPopMatrix();
- gpuMatrixEnd();
immUnbindProgram();
}
@@ -1651,7 +1795,6 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
if (!ok && scopes->track_preview) {
- gpuMatrixBegin3D_legacy();
gpuPushMatrix();
/* draw content of pattern area */
@@ -1659,7 +1802,6 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
if (width > 0 && height > 0) {
ImBuf *drawibuf = scopes->track_preview;
- float img_col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
float col_sel[4], col_outline[4];
if (scopes->use_track_mask) {
@@ -1668,10 +1810,11 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
UI_draw_roundbox_gl_mode(GL_TRIANGLE_FAN, rect.xmin - 1, rect.ymin, rect.xmax + 1, rect.ymax + 1, 3.0f, color);
}
- immDrawPixelsTex(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, img_col);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(rect.xmin, rect.ymin + 1, drawibuf->x, drawibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, drawibuf->rect, 1.0f, 1.0f, NULL);
/* draw cross for pixel position */
- gpuTranslate3f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1], 0.0f);
+ gpuTranslate2f(rect.xmin + scopes->track_pos[0], rect.ymin + scopes->track_pos[1]);
glScissor(ar->winrct.xmin + rect.xmin,
ar->winrct.ymin + rect.ymin,
BLI_rctf_size_x(&rect),
@@ -1710,7 +1853,6 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc
}
gpuPopMatrix();
- gpuMatrixEnd();
ok = true;
}
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index a50c0f5a4f4..f0a8527f9a4 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -1082,7 +1082,7 @@ static int depthdropper_poll(bContext *C)
return 1;
}
}
- else {
+ else {
RegionView3D *rv3d = CTX_wm_region_view3d(C);
if (rv3d && rv3d->persp == RV3D_CAMOB) {
View3D *v3d = CTX_wm_view3d(C);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9bdc4d29807..ccf1c7305a9 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -87,6 +87,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "wm_event_system.h"
#ifdef WITH_INPUT_IME
# include "wm_window.h"
@@ -200,7 +201,9 @@ static void ui_selectcontext_apply(
bContext *C, uiBut *but, struct uiSelectContextStore *selctx_data,
const double value, const double value_orig);
+#if 0
#define IS_ALLSELECT_EVENT(event) ((event)->alt != 0)
+#endif
/** just show a tinted color so users know its activated */
#define UI_BUT_IS_SELECT_CONTEXT UI_BUT_NODE_ACTIVE
@@ -379,6 +382,7 @@ typedef struct uiAfterFunc {
void *butm_func_arg;
int a2;
+ wmOperator *popup_op;
wmOperatorType *optype;
int opcontext;
PointerRNA *opptr;
@@ -634,13 +638,24 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
return ptr;
}
+static void popup_check(bContext *C, wmOperator *op)
+{
+ if (op && op->type->check && op->type->check(C, op)) {
+ /* check for popup and re-layout buttons */
+ ARegion *ar_menu = CTX_wm_menu(C);
+ if (ar_menu)
+ ED_region_tag_refresh_ui(ar_menu);
+ }
+}
+
/**
* 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));
+ (but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
+ (block->handle && block->handle->popup_op));
}
static void ui_apply_but_func(bContext *C, uiBut *but)
@@ -681,6 +696,9 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
after->butm_func_arg = block->butm_func_arg;
after->a2 = but->a2;
}
+
+ if (block->handle)
+ after->popup_op = block->handle->popup_op;
after->optype = but->optype;
after->opcontext = but->opcontext;
@@ -765,6 +783,9 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.context)
CTX_store_set(C, after.context);
+ if (after.popup_op)
+ popup_check(C, after.popup_op);
+
if (after.opptr) {
/* free in advance to avoid leak on exit */
opptr = *after.opptr;
@@ -2092,6 +2113,7 @@ static void ui_apply_but(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
break;
case UI_BTYPE_ROW:
case UI_BTYPE_LISTROW:
+ case UI_BTYPE_TAB:
ui_apply_but_ROW(C, block, but, data);
break;
case UI_BTYPE_SCROLL:
@@ -3833,6 +3855,18 @@ static int ui_do_but_KEYEVT(
return WM_UI_HANDLER_CONTINUE;
}
+static int ui_do_but_TAB(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
+{
+ if (data->state == BUTTON_STATE_HIGHLIGHT) {
+ if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_RELEASE) {
+ button_activate_state(C, but, BUTTON_STATE_EXIT);
+ return WM_UI_HANDLER_CONTINUE;
+ }
+ }
+
+ return WM_UI_HANDLER_CONTINUE;
+}
+
static bool ui_but_is_mouse_over_icon_extra(const ARegion *region, uiBut *but, const int mouse_xy[2])
{
int x = mouse_xy[0], y = mouse_xy[1];
@@ -5177,7 +5211,8 @@ static int ui_do_but_COLOR(
if (!event->ctrl) {
float color[3];
Scene *scene = CTX_data_scene(C);
- Paint *paint = BKE_paint_get_active(scene);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Paint *paint = BKE_paint_get_active(scene, sl);
Brush *brush = BKE_paint_brush(paint);
if (brush->flag & BRUSH_USE_GRADIENT) {
@@ -6085,6 +6120,7 @@ static int ui_do_but_CURVE(
int mx, my, a;
bool changed = false;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
mx = event->x;
my = event->y;
@@ -6213,7 +6249,7 @@ static int ui_do_but_CURVE(
}
else {
curvemapping_changed(cumap, true); /* remove doubles */
- BKE_paint_invalidate_cursor_overlay(scene, cumap);
+ BKE_paint_invalidate_cursor_overlay(scene, sl, cumap);
}
}
@@ -6643,7 +6679,7 @@ static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
{
uiBut *but = (uiBut *)arg1;
- UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but);
+ UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL);
}
/**
@@ -6983,20 +7019,17 @@ static bool ui_but_menu(bContext *C, uiBut *but)
uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"),
ICON_URL, "WM_OT_doc_view_manual_ui_context");
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_view");
+ ptr_props = uiItemFullO(layout, "WM_OT_doc_view",
+ CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
+ ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr_props, "doc_id", buf);
- uiItemFullO(layout, "WM_OT_doc_view",
- CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"),
- ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0);
/* XXX inactive option, not for public! */
#if 0
- WM_operator_properties_create(&ptr_props, "WM_OT_doc_edit");
+ ptr_props = uiItemFullO(layout, "WM_OT_doc_edit",
+ "Submit Description", ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr_props, "doc_id", buf);
RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop));
-
- uiItemFullO(layout, "WM_OT_doc_edit",
- "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0);
#endif
}
}
@@ -7076,6 +7109,9 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
case UI_BTYPE_HOTKEY_EVENT:
retval = ui_do_but_HOTKEYEVT(C, but, data, event);
break;
+ case UI_BTYPE_TAB:
+ retval = ui_do_but_TAB(C, but, data, event);
+ break;
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_ICON_TOGGLE:
@@ -7719,7 +7755,8 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
if (ui_but_is_cursor_warp(but)) {
#ifdef USE_CONT_MOUSE_CORRECT
- if (data->ungrab_mval[0] != FLT_MAX) {
+ /* stereo3d has issues with changing cursor location so rather avoid */
+ if (data->ungrab_mval[0] != FLT_MAX && !WM_stereo3d_enabled(data->window, false)) {
int mouse_ungrab_xy[2];
ui_block_to_window_fl(data->region, but->block, &data->ungrab_mval[0], &data->ungrab_mval[1]);
mouse_ungrab_xy[0] = data->ungrab_mval[0];
@@ -10159,6 +10196,25 @@ void UI_popup_handlers_add(bContext *C, ListBase *handlers, uiPopupBlockHandle *
void UI_popup_handlers_remove(ListBase *handlers, uiPopupBlockHandle *popup)
{
+ wmEventHandler *handler;
+
+ for (handler = handlers->first; handler; handler = handler->next) {
+ if (handler->ui_handle == ui_popup_handler &&
+ handler->ui_remove == ui_popup_handler_remove &&
+ handler->ui_userdata == popup)
+ {
+ /* tag refresh parent popup */
+ if (handler->next &&
+ handler->next->ui_handle == ui_popup_handler &&
+ handler->next->ui_remove == ui_popup_handler_remove)
+ {
+ uiPopupBlockHandle *parent_popup = handler->next->ui_userdata;
+ ED_region_tag_refresh_ui(parent_popup->region);
+ }
+ break;
+ }
+ }
+
WM_event_remove_ui_handler(handlers, ui_popup_handler, ui_popup_handler_remove, popup, false);
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index a9cdb34f634..cc7f1532b9d 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -33,8 +33,6 @@
#include "MEM_guardedalloc.h"
-#include "GPU_extensions.h"
-#include "GPU_basic_shader.h"
#include "GPU_draw.h"
#include "GPU_immediate.h"
@@ -264,12 +262,12 @@ static void vicon_keytype_draw_wrapper(int x, int y, int w, int h, float alpha,
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_enable_program_point_size();
immBegin(PRIM_POINTS, 1);
-
+
/* draw keyframe
- * - size: 0.3 * h (found out experimentally... dunno why!)
+ * - size: 0.6 * h (found out experimentally... dunno why!)
* - sel: true (so that "keyframe" state shows the iconic yellow icon)
*/
- draw_keyframe_shape(xco, yco, 0.3f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha,
+ draw_keyframe_shape(xco, yco, 0.6f * h, true, key_type, KEYFRAME_SHAPE_BOTH, alpha,
pos_id, size_id, color_id, outline_color_id);
immEnd();
@@ -961,7 +959,7 @@ PreviewImage *UI_icon_to_preview(int icon_id)
}
static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect), int rw, int rh,
- unsigned int *rect, float alpha, const float rgb[3], const bool is_preview)
+ unsigned int *rect, float alpha, const float rgb[3], const bool UNUSED(is_preview))
{
ImBuf *ima = NULL;
int draw_w = w;
@@ -975,15 +973,13 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
BLI_assert(!"invalid icon size");
return;
}
-
/* modulate color */
- if (alpha != 1.0f)
- glPixelTransferf(GL_ALPHA_SCALE, alpha);
+ float col[4] = {1.0f, 1.0f, 1.0f, alpha};
if (rgb) {
- glPixelTransferf(GL_RED_SCALE, rgb[0]);
- glPixelTransferf(GL_GREEN_SCALE, rgb[1]);
- glPixelTransferf(GL_BLUE_SCALE, rgb[2]);
+ col[0] = rgb[0];
+ col[1] = rgb[1];
+ col[2] = rgb[2];
}
/* rect contains image in 'rendersize', we only scale if needed */
@@ -1009,31 +1005,12 @@ static void icon_draw_rect(float x, float y, int w, int h, float UNUSED(aspect),
}
/* draw */
- if (is_preview) {
- glaDrawPixelsSafe(draw_x, draw_y, draw_w, draw_h, draw_w, GL_RGBA, GL_UNSIGNED_BYTE, rect);
- }
- else {
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
-
- glRasterPos2f(draw_x, draw_y);
- glDrawPixels(draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, rect);
-
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
- }
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(draw_x, draw_y, draw_w, draw_h, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect,
+ 1.0f, 1.0f, col);
if (ima)
IMB_freeImBuf(ima);
-
- /* restore color */
- if (alpha != 0.0f)
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
-
- if (rgb) {
- glPixelTransferf(GL_RED_SCALE, 1.0f);
- glPixelTransferf(GL_GREEN_SCALE, 1.0f);
- glPixelTransferf(GL_BLUE_SCALE, 1.0f);
- }
}
static void icon_draw_texture(
@@ -1051,9 +1028,9 @@ static void icon_draw_texture(
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, -0.5f);
glBindTexture(GL_TEXTURE_2D, icongltex.id);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
if (rgb) immUniformColor3fvAlpha(rgb, alpha);
@@ -1080,7 +1057,6 @@ static void icon_draw_texture(
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, 0.0f);
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
/* Drawing size for preview images */
@@ -1407,14 +1383,6 @@ int UI_idcode_icon_get(const int idcode)
}
}
-/**
- * \param set_idx: A value from #rna_enum_color_sets_items.
- */
-int UI_colorset_icon_get(const int set_idx)
-{
- return (set_idx < 1) ? ICON_NONE : VICO_COLORSET_01_VEC - 1 + set_idx;
-}
-
static void icon_draw_at_size(
float x, float y, int icon_id, float aspect, float alpha,
enum eIconSizes size, const bool nocreate)
@@ -1440,6 +1408,11 @@ void UI_icon_draw(float x, float y, int icon_id)
UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, 1.0f);
}
+void UI_icon_draw_alpha(float x, float y, int icon_id, float alpha)
+{
+ UI_icon_draw_aspect(x, y, icon_id, 1.0f / UI_DPI_FAC, alpha);
+}
+
void UI_icon_draw_size(float x, float y, int size, int icon_id, float alpha)
{
icon_draw_size(x, y, icon_id, 1.0f, alpha, NULL, ICON_SIZE_ICON, size, true, false);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index 7529f60c6f0..68bb48f66fb 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -72,6 +72,7 @@ typedef enum {
UI_WTYPE_NUMBER,
UI_WTYPE_SLIDER,
UI_WTYPE_EXEC,
+ UI_WTYPE_TAB,
UI_WTYPE_TOOLTIP,
/* strings */
@@ -556,6 +557,7 @@ struct uiPopupBlockHandle {
struct uiKeyNavLock keynav_state;
/* for operator popups */
+ struct wmOperator *popup_op;
struct wmOperatorType *optype;
ScrArea *ctx_area;
ARegion *ctx_region;
@@ -639,6 +641,8 @@ extern void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, floa
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha);
+
+void ui_draw_but_TAB_outline(const rcti *rect, float rad, unsigned char highlight[3], unsigned char highlight_fade[3]);
void ui_draw_but_HISTOGRAM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
void ui_draw_but_VECTORSCOPE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect);
@@ -681,7 +685,7 @@ struct wmIMEData *ui_but_ime_data_get(uiBut *but);
#endif
/* interface_widgets.c */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]);
void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy,
float rad, bool use_alpha, const float color[4]);
void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect);
@@ -690,7 +694,7 @@ uiWidgetColors *ui_tooltip_get_theme(void);
void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock *block, rcti *rect);
void ui_draw_search_back(struct uiStyle *style, uiBlock *block, rcti *rect);
bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol);
-void ui_draw_link_bezier(const rcti *rect);
+void ui_draw_link_bezier(const rcti *rect, const float color[4]);
extern void ui_draw_but(const struct bContext *C, ARegion *ar, struct uiStyle *style, uiBut *but, rcti *rect);
/* theme color init */
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index ca2538022b0..9b6547cf8a1 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -189,7 +189,7 @@ static const char *ui_item_name_add_colon(const char *name, char namestr[UI_MAX_
return name;
}
-static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment)
+static int ui_item_fit(int item, int pos, int all, int available, bool is_last, int alignment, float *extra_pixel)
{
/* available == 0 is unlimited */
if (available == 0)
@@ -199,16 +199,22 @@ static int ui_item_fit(int item, int pos, int all, int available, bool is_last,
/* contents is bigger than available space */
if (is_last)
return available - pos;
- else
- return (item * available) / all;
+ else {
+ float width = *extra_pixel + (item * available) / (float)all;
+ *extra_pixel = width - (int)width;
+ return (int)width;
+ }
}
else {
/* contents is smaller or equal to available space */
if (alignment == UI_LAYOUT_ALIGN_EXPAND) {
if (is_last)
return available - pos;
- else
- return (item * available) / all;
+ else {
+ float width = *extra_pixel + (item * available) / (float)all;
+ *extra_pixel = width - (int)width;
+ return (int)width;
+ }
}
else
return item;
@@ -302,6 +308,26 @@ static void ui_item_position(uiItem *item, int x, int y, int w, int h)
}
}
+static void ui_item_move(uiItem *item, int delta_xmin, int delta_xmax)
+{
+ if (item->type == ITEM_BUTTON) {
+ uiButtonItem *bitem = (uiButtonItem *)item;
+
+ bitem->but->rect.xmin += delta_xmin;
+ bitem->but->rect.xmax += delta_xmax;
+
+ ui_but_update(bitem->but); /* for strlen */
+ }
+ else {
+ uiLayout *litem = (uiLayout *)item;
+
+ if (delta_xmin > 0)
+ litem->x += delta_xmin;
+ else
+ litem->w += delta_xmax;
+ }
+}
+
/******************** Special RNA Items *********************/
static int ui_layout_local_dir(uiLayout *layout)
@@ -2099,9 +2125,10 @@ static int ui_litem_min_width(int itemw)
static void ui_litem_layout_row(uiLayout *litem)
{
- uiItem *item;
+ uiItem *item, *last_free_item = NULL;
int x, y, w, tot, totw, neww, newtotw, itemw, minw, itemh, offset;
int fixedw, freew, fixedx, freex, flag = 0, lastw = 0;
+ float extra_pixel;
/* x = litem->x; */ /* UNUSED */
y = litem->y;
@@ -2128,6 +2155,7 @@ static void ui_litem_layout_row(uiLayout *litem)
x = 0;
flag = 0;
newtotw = totw;
+ extra_pixel = 0.0f;
for (item = litem->items.first; item; item = item->next) {
if (item->flag & UI_ITEM_FIXED)
@@ -2137,13 +2165,23 @@ static void ui_litem_layout_row(uiLayout *litem)
minw = ui_litem_min_width(itemw);
if (w - lastw > 0)
- neww = ui_item_fit(itemw, x, totw, w - lastw, !item->next, litem->alignment);
+ neww = ui_item_fit(itemw, x, totw, w - lastw, !item->next, litem->alignment, &extra_pixel);
else
neww = 0; /* no space left, all will need clamping to minimum size */
x += neww;
- if ((neww < minw || itemw == minw || item->flag & UI_ITEM_MIN) && w != 0) {
+ bool min_flag = item->flag & UI_ITEM_MIN;
+ /* ignore min flag for rows with right or center alignment */
+ if (item->type != ITEM_BUTTON &&
+ ELEM(((uiLayout *)item)->alignment, UI_LAYOUT_ALIGN_RIGHT, UI_LAYOUT_ALIGN_CENTER) &&
+ litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
+ ((uiItem *)litem)->flag & UI_ITEM_MIN)
+ {
+ min_flag = false;
+ }
+
+ if ((neww < minw || min_flag) && w != 0) {
/* fixed size */
item->flag |= UI_ITEM_FIXED;
if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
@@ -2166,6 +2204,7 @@ static void ui_litem_layout_row(uiLayout *litem)
freex = 0;
fixedx = 0;
+ extra_pixel = 0.0f;
x = litem->x;
for (item = litem->items.first; item; item = item->next) {
@@ -2177,13 +2216,14 @@ static void ui_litem_layout_row(uiLayout *litem)
if (item->type != ITEM_BUTTON && item->flag & UI_ITEM_MIN) {
minw = itemw;
}
- itemw = ui_item_fit(minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment);
+ itemw = ui_item_fit(minw, fixedx, fixedw, min_ii(w, fixedw), !item->next, litem->alignment, &extra_pixel);
fixedx += itemw;
}
else {
/* free size item */
- itemw = ui_item_fit(itemw, freex, freew, w - fixedw, !item->next, litem->alignment);
+ itemw = ui_item_fit(itemw, freex, freew, w - fixedw, !item->next, litem->alignment, &extra_pixel);
freex += itemw;
+ last_free_item = item;
}
/* align right/center */
@@ -2205,6 +2245,17 @@ static void ui_litem_layout_row(uiLayout *litem)
x += litem->space;
}
+ /* add extra pixel */
+ uiItem *last_item = litem->items.last;
+ extra_pixel = litem->w - (x - litem->x);
+ if (extra_pixel > 0 && litem->alignment == UI_LAYOUT_ALIGN_EXPAND &&
+ last_free_item && last_item && last_item->flag & UI_ITEM_FIXED)
+ {
+ ui_item_move(last_free_item, 0, extra_pixel);
+ for (item = last_free_item->next; item; item = item->next)
+ ui_item_move(item, extra_pixel, extra_pixel);
+ }
+
litem->w = x - litem->x;
litem->h = litem->y - y;
litem->x = x;
@@ -2212,7 +2263,7 @@ static void ui_litem_layout_row(uiLayout *litem)
}
/* single-column layout */
-static void ui_litem_estimate_column(uiLayout *litem)
+static void ui_litem_estimate_column(uiLayout *litem, bool is_box)
{
uiItem *item;
int itemw, itemh;
@@ -2229,16 +2280,16 @@ static void ui_litem_estimate_column(uiLayout *litem)
litem->w = MAX2(litem->w, itemw);
litem->h += itemh;
- if (item->next)
+ if (item->next && (!is_box || item != litem->items.first))
litem->h += litem->space;
}
-
+
if (min_size_flag) {
litem->item.flag |= UI_ITEM_MIN;
}
}
-static void ui_litem_layout_column(uiLayout *litem)
+static void ui_litem_layout_column(uiLayout *litem, bool is_box)
{
uiItem *item;
int itemh, x, y;
@@ -2252,7 +2303,7 @@ static void ui_litem_layout_column(uiLayout *litem)
y -= itemh;
ui_item_position(item, x, y, litem->w, itemh);
- if (item->next)
+ if (item->next && (!is_box || item != litem->items.first))
y -= litem->space;
}
@@ -2394,7 +2445,7 @@ static void ui_litem_layout_root(uiLayout *litem)
else if (litem->root->type == UI_LAYOUT_PIEMENU)
ui_litem_layout_root_radial(litem);
else
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, false);
}
/* box layout */
@@ -2402,9 +2453,10 @@ static void ui_litem_estimate_box(uiLayout *litem)
{
uiStyle *style = litem->root->style;
- ui_litem_estimate_column(litem);
+ ui_litem_estimate_column(litem, true);
+ litem->item.flag &= ~UI_ITEM_MIN;
litem->w += 2 * style->boxspace;
- litem->h += style->boxspace;
+ litem->h += 2 * style->boxspace;
}
static void ui_litem_layout_box(uiLayout *litem)
@@ -2418,17 +2470,18 @@ static void ui_litem_layout_box(uiLayout *litem)
h = litem->h;
litem->x += style->boxspace;
+ litem->y -= style->boxspace;
if (w != 0) litem->w -= 2 * style->boxspace;
if (h != 0) litem->h -= 2 * style->boxspace;
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, true);
litem->x -= style->boxspace;
litem->y -= style->boxspace;
if (w != 0) litem->w += 2 * style->boxspace;
- if (h != 0) litem->h += style->boxspace;
+ if (h != 0) litem->h += 2 * style->boxspace;
/* roundbox around the sublayout */
but = box->roundbox;
@@ -2648,13 +2701,14 @@ static void ui_litem_layout_absolute(uiLayout *litem)
static void ui_litem_estimate_split(uiLayout *litem)
{
ui_litem_estimate_row(litem);
+ litem->item.flag &= ~UI_ITEM_MIN;
}
static void ui_litem_layout_split(uiLayout *litem)
{
uiLayoutItemSplit *split = (uiLayoutItemSplit *)litem;
uiItem *item;
- float percentage;
+ float percentage, extra_pixel = 0.0f;
const int tot = BLI_listbase_count(&litem->items);
int itemh, x, y, w, colw = 0;
@@ -2677,7 +2731,9 @@ static void ui_litem_layout_split(uiLayout *litem)
x += colw;
if (item->next) {
- colw = (w - (int)(w * percentage)) / (tot - 1);
+ const float width = extra_pixel + (w - (int)(w * percentage)) / ((float)tot - 1);
+ extra_pixel = width - (int)width;
+ colw = (int)width;
colw = MAX2(colw, 0);
x += litem->space;
@@ -3078,7 +3134,7 @@ static void ui_item_estimate(uiItem *item)
switch (litem->item.type) {
case ITEM_LAYOUT_COLUMN:
- ui_litem_estimate_column(litem);
+ ui_litem_estimate_column(litem, false);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_estimate_column_flow(litem);
@@ -3133,9 +3189,9 @@ static void ui_item_align(uiLayout *litem, short nr)
}
else if (item->type == ITEM_LAYOUT_BOX) {
box = (uiLayoutItemBx *)item;
- box->roundbox->alignnr = nr;
- BLI_remlink(&litem->root->block->buttons, box->roundbox);
- BLI_addhead(&litem->root->block->buttons, box->roundbox);
+ if (!box->roundbox->alignnr) {
+ box->roundbox->alignnr = nr;
+ }
}
else if (((uiLayout *)item)->align) {
ui_item_align((uiLayout *)item, nr);
@@ -3177,7 +3233,7 @@ static void ui_item_layout(uiItem *item)
switch (litem->item.type) {
case ITEM_LAYOUT_COLUMN:
- ui_litem_layout_column(litem);
+ ui_litem_layout_column(litem, false);
break;
case ITEM_LAYOUT_COLUMN_FLOW:
ui_litem_layout_column_flow(litem);
@@ -3521,14 +3577,13 @@ void uiLayoutOperatorButs(
row = uiLayoutRow(layout, true);
uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE);
- WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false);
+ op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMIN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "operator", op->type->idname);
- uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
- WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add");
+ op_ptr = uiItemFullO_ptr(row, ot, "", ICON_ZOOMOUT, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "operator", op->type->idname);
RNA_boolean_set(&op_ptr, "remove_active", true);
- uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
}
if (op->type->ui) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 40ebc946e79..de226e74c65 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -42,6 +42,8 @@
#include "BLT_lang.h"
#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_screen.h"
#include "BKE_global.h"
#include "BKE_node.h"
@@ -50,6 +52,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
+#include "RNA_types.h"
#include "UI_interface.h"
@@ -328,6 +331,109 @@ static void UI_OT_unset_property_button(wmOperatorType *ot)
ot->flag = OPTYPE_UNDO;
}
+/* Use/Unuse Property Button Operator ------------------------ */
+
+static int use_property_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr, scene_props_ptr;
+ PropertyRNA *prop;
+ IDProperty *props;
+
+ uiBut *but = UI_context_active_but_get(C);
+
+ prop = but->rnaprop;
+ ptr = but->rnapoin;
+ props = (IDProperty *)ptr.data;
+ /* XXX Using existing data struct to pass another RNAPointer */
+ scene_props_ptr = but->rnasearchpoin;
+
+ const char *identifier = RNA_property_identifier(prop);
+ if (IDP_GetPropertyFromGroup(props, identifier)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ switch (RNA_property_type(prop)) {
+ case PROP_FLOAT:
+ {
+ float value = RNA_property_float_get(&scene_props_ptr, prop);
+ BKE_collection_engine_property_add_float(props, identifier, value);
+ break;
+ }
+ case PROP_ENUM:
+ {
+ int value = RNA_enum_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_int(props, identifier, value);
+ break;
+ }
+ case PROP_INT:
+ {
+ int value = RNA_int_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_int(props, identifier, value);
+ break;
+ }
+ case PROP_BOOLEAN:
+ {
+ int value = RNA_boolean_get(&scene_props_ptr, identifier);
+ BKE_collection_engine_property_add_bool(props, identifier, value);
+ break;
+ }
+ case PROP_STRING:
+ case PROP_POINTER:
+ case PROP_COLLECTION:
+ default:
+ break;
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_use_property_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Use property";
+ ot->idname = "UI_OT_use_property_button";
+ ot->description = "Create a property";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = use_property_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
+static int unuse_property_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+
+ /* try to unset the nominated property */
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+ const char *identifier = RNA_property_identifier(prop);
+
+ IDProperty *props = (IDProperty *)ptr.data;
+ IDProperty *prop_to_remove = IDP_GetPropertyFromGroup(props, identifier);
+ IDP_FreeFromGroup(props, prop_to_remove);
+
+ return OPERATOR_FINISHED;
+}
+
+static void UI_OT_unuse_property_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Unuse property";
+ ot->idname = "UI_OT_unuse_property_button";
+ ot->description = "Remove a property";
+
+ /* callbacks */
+ ot->poll = ED_operator_regionactive;
+ ot->exec = unuse_property_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
+
/* Copy To Selected Operator ------------------------ */
bool UI_context_copy_to_selected_list(
@@ -739,6 +845,7 @@ static int editsource_text_edit(
if (text == NULL) {
text = BKE_text_load(bmain, filepath, bmain->name);
+ id_us_ensure_real(&text->id);
}
if (text == NULL) {
@@ -1113,6 +1220,8 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_copy_python_command_button);
WM_operatortype_append(UI_OT_reset_default_button);
WM_operatortype_append(UI_OT_unset_property_button);
+ WM_operatortype_append(UI_OT_use_property_button);
+ WM_operatortype_append(UI_OT_unuse_property_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c
index 1bdc47e5037..acadcdf3e3e 100644
--- a/source/blender/editors/interface/interface_panel.c
+++ b/source/blender/editors/interface/interface_panel.c
@@ -50,9 +50,6 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "BLF_api.h"
#include "WM_api.h"
@@ -395,54 +392,41 @@ static void ui_offset_panel_block(uiBlock *block)
/**************************** drawing *******************************/
-/* extern used by previewrender */
-#if 0 /*UNUSED 2.5*/
-static void uiPanelPush(uiBlock *block)
-{
- glPushMatrix();
-
- if (block->panel)
- glTranslatef((float)block->panel->ofsx, (float)block->panel->ofsy, 0.0);
-}
-
-static void uiPanelPop(uiBlock *UNUSED(block))
-{
- glPopMatrix();
-}
-#endif
-
/* triangle 'icon' for panel header */
-void UI_draw_icon_tri(float x, float y, char dir)
+void UI_draw_icon_tri(float x, float y, char dir, const float color[4])
{
float f3 = 0.15 * U.widget_unit;
float f5 = 0.25 * U.widget_unit;
float f7 = 0.35 * U.widget_unit;
if (dir == 'h') {
- ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y);
+ ui_draw_anti_tria(x - f3, y - f5, x - f3, y + f5, x + f7, y, color);
}
else if (dir == 't') {
- ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3);
+ ui_draw_anti_tria(x - f5, y - f7, x + f5, y - f7, x, y + f3, color);
}
else { /* 'v' = vertical, down */
- ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7);
+ ui_draw_anti_tria(x - f5, y + f3, x + f5, y + f3, x, y - f7, color);
}
}
/* triangle 'icon' inside rect */
static void ui_draw_tria_rect(const rctf *rect, char dir)
{
+ float color[4];
+ UI_GetThemeColor4fv(TH_TITLE, color);
+
if (dir == 'h') {
float half = 0.5f * BLI_rctf_size_y(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half);
+ ui_draw_anti_tria(rect->xmin, rect->ymin, rect->xmin, rect->ymax, rect->xmax, rect->ymin + half, color);
}
else {
float half = 0.5f * BLI_rctf_size_x(rect);
- ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin);
+ ui_draw_anti_tria(rect->xmin, rect->ymax, rect->xmax, rect->ymax, rect->xmin + half, rect->ymin, color);
}
}
-static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
+static void ui_draw_anti_x(unsigned int pos, float x1, float y1, float x2, float y2)
{
/* set antialias line */
@@ -450,9 +434,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
glEnable(GL_BLEND);
glLineWidth(2.0);
-
- fdrawline(x1, y1, x2, y2);
- fdrawline(x1, y2, x2, y1);
+
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y2);
+
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y1);
+
+ immEnd();
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -460,16 +451,16 @@ static void ui_draw_anti_x(float x1, float y1, float x2, float y2)
}
/* x 'icon' for panel header */
-static void ui_draw_x_icon(float x, float y)
+static void ui_draw_x_icon(unsigned int pos, float x, float y)
{
- ui_draw_anti_x(x, y, x + 9.375f, y + 9.375f);
+ ui_draw_anti_x(pos, x, y, x + 9.375f, y + 9.375f);
}
#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */
-static void ui_draw_panel_scalewidget(const rcti *rect)
+static void ui_draw_panel_scalewidget(unsigned int pos, const rcti *rect)
{
float xmin, xmax, dx;
float ymin, ymax, dy;
@@ -483,16 +474,33 @@ static void ui_draw_panel_scalewidget(const rcti *rect)
dy = 0.5f * (ymax - ymin);
glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 50);
- fdrawline(xmin, ymin, xmax, ymax);
- fdrawline(xmin + dx, ymin, xmax, ymax - dy);
+ immUniformColor4ub(255, 255, 255, 50);
+
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin);
+ immVertex2f(pos, xmax, ymax);
+
+ immVertex2f(pos, xmin + dx, ymin);
+ immVertex2f(pos, xmax, ymax - dy);
+
+ immEnd();
- glColor4ub(0, 0, 0, 50);
- fdrawline(xmin, ymin + 1, xmax, ymax + 1);
- fdrawline(xmin + dx, ymin + 1, xmax, ymax - dy + 1);
+ immUniformColor4ub(0, 0, 0, 50);
+
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, xmin, ymin + 1);
+ immVertex2f(pos, xmax, ymax + 1);
+
+ immVertex2f(pos, xmin + dx, ymin + 1);
+ immVertex2f(pos, xmax, ymax - dy + 1);
+
+ immEnd();
+
glDisable(GL_BLEND);
}
-static void ui_draw_panel_dragwidget(const rctf *rect)
+static void ui_draw_panel_dragwidget(unsigned int pos, const rctf *rect)
{
unsigned char col_back[3], col_high[3], col_dark[3];
const int col_tint = 84;
@@ -521,10 +529,10 @@ static void ui_draw_panel_dragwidget(const rctf *rect)
const int x_co = (x_min + x_ofs) + (i_x * (box_size + box_margin));
const int y_co = (y_min + y_ofs) + (i_y * (box_size + box_margin));
- glColor3ubv(col_dark);
- glRectf(x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
- glColor3ubv(col_high);
- glRectf(x_co - box_size, y_co, x_co, y_co + box_size);
+ immUniformColor3ubv(col_dark);
+ immRectf(pos, x_co - box_size, y_co - px_zoom, x_co, (y_co + box_size) - px_zoom);
+ immUniformColor3ubv(col_high);
+ immRectf(pos, x_co - box_size, y_co, x_co, y_co + box_size);
}
}
}
@@ -582,6 +590,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
headrect.ymin = headrect.ymax;
headrect.ymax = headrect.ymin + floor(PNL_HEADER / block->aspect + 0.001f);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
{
float minx = rect->xmin;
float maxx = is_closed_x ? (minx + PNL_HEADER / block->aspect) : rect->xmax;
@@ -591,11 +602,18 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
if (UI_GetThemeValue(TH_PANEL_SHOW_HEADER)) {
/* draw with background color */
- UI_ThemeColor4(TH_PANEL_HEADER);
- glRectf(minx, headrect.ymin + 1, maxx, y);
+ immUniformThemeColor(TH_PANEL_HEADER);
+ immRectf(pos, minx, headrect.ymin + 1, maxx, y);
+
+ immBegin(GL_LINES, 4);
- fdrawline(minx, y, maxx, y);
- fdrawline(minx, y, maxx, y);
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+
+ immEnd();
}
else if (!(panel->runtime_flag & PNL_FIRST)) {
/* draw embossed separator */
@@ -605,15 +623,26 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
maxx -= 5.0f / block->aspect;
}
- glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
- fdrawline(minx, y, maxx, y);
- glColor4f(1.0f, 1.0f, 1.0f, 0.25f);
- fdrawline(minx, y - 1, maxx, y - 1);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, minx, y);
+ immVertex2f(pos, maxx, y);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.25f);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, minx, y - 1);
+ immVertex2f(pos, maxx, y - 1);
+ immEnd();
}
glDisable(GL_BLEND);
}
+ immUnbindProgram();
+
/* draw optional pin icon */
#ifdef USE_PIN_HIDDEN
@@ -629,9 +658,11 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
glDisable(GL_BLEND);
}
+
/* horizontal title */
if (is_closed_x == false) {
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
/* itemrect smaller */
itemrect.xmax = headrect.xmax - 5.0f / block->aspect;
@@ -640,7 +671,9 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
itemrect.ymax = headrect.ymax;
BLI_rctf_scale(&itemrect, 0.7f);
- ui_draw_panel_dragwidget(&itemrect);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ ui_draw_panel_dragwidget(pos, &itemrect);
+ immUnbindProgram();
}
/* if the panel is minimized vertically:
@@ -652,6 +685,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
else if (is_closed_x) {
/* draw vertical title */
ui_draw_aligned_panel_header(style, block, &headrect, 'v');
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
}
/* an open panel */
else {
@@ -664,29 +698,34 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
UI_draw_roundbox_unfilled(0.5f + rect->xmin, 0.5f + rect->ymin, 0.5f + rect->xmax, 0.5f + headrect.ymax + 1, 8, color);
}
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* panel backdrop */
if (UI_GetThemeValue(TH_PANEL_SHOW_BACK)) {
/* draw with background color */
glEnable(GL_BLEND);
- UI_ThemeColor4(TH_PANEL_BACK);
- glRecti(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+ immUniformThemeColor(TH_PANEL_BACK);
+ immRectf(pos, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
}
if (panel->control & UI_PNL_SCALE)
- ui_draw_panel_scalewidget(rect);
+ ui_draw_panel_scalewidget(pos, rect);
+
+ immUnbindProgram();
}
/* draw optional close icon */
ofsx = 6;
if (panel->control & UI_PNL_CLOSE) {
- UI_ThemeColor(TH_TITLE);
- ui_draw_x_icon(rect->xmin + 2 + ofsx, rect->ymax + 2);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_TITLE);
+ ui_draw_x_icon(pos, rect->xmin + 2 + ofsx, rect->ymax + 2);
ofsx = 22;
+ immUnbindProgram();
}
/* draw collapse icon */
- UI_ThemeColor(TH_TITLE);
/* itemrect smaller */
itemrect.xmin = headrect.xmin + 5.0f / block->aspect;
@@ -703,6 +742,7 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, con
else
ui_draw_tria_rect(&itemrect, 'v');
+
(void)ofsx;
}
@@ -1540,10 +1580,6 @@ static void ui_panel_category_draw_tab(
mul_v2_fl(vec[a], rad);
}
- if (mode == GL_POLYGON) {
- mode = GL_TRIANGLE_FAN;
- }
-
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
immBeginAtMost(mode, 24);
@@ -1735,21 +1771,26 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* begin drawing */
glEnable(GL_LINE_SMOOTH);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw the background */
if (is_alpha) {
glEnable(GL_BLEND);
- glColor4ubv(theme_col_tab_bg);
+ immUniformColor4ubv(theme_col_tab_bg);
}
else {
- glColor3ubv(theme_col_tab_bg);
+ immUniformColor3ubv(theme_col_tab_bg);
}
- glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
+ immRecti(pos, v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
if (is_alpha) {
glDisable(GL_BLEND);
}
+ immUnbindProgram();
+
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
const rcti *rct = &pc_dyn->rect;
const char *category_id = pc_dyn->idname;
@@ -1772,7 +1813,7 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
if (is_active)
#endif
{
- ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
+ ui_panel_category_draw_tab(GL_TRIANGLE_FAN, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
tab_curve_radius - px, roundboxtype, true, true, NULL,
is_active ? theme_col_tab_active : theme_col_tab_inactive);
@@ -1789,11 +1830,16 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
/* tab blackline */
if (!is_active) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymin - tab_v_pad,
- v2d->mask.xmin + category_tabs_width,
- rct->ymax + tab_v_pad);
+ pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymin - tab_v_pad,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymax + tab_v_pad);
+
+ immUnbindProgram();
}
if (do_scaletabs) {
@@ -1814,33 +1860,36 @@ void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
glDisable(GL_BLEND);
/* tab blackline remaining (last tab) */
+ pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (pc_dyn->prev == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- rct->ymax + px,
- v2d->mask.xmin + category_tabs_width,
- v2d->mask.ymax);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ rct->ymax + px,
+ v2d->mask.xmin + category_tabs_width,
+ v2d->mask.ymax);
}
if (pc_dyn->next == NULL) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + category_tabs_width - px,
- 0,
- v2d->mask.xmin + category_tabs_width,
- rct->ymin);
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + category_tabs_width - px,
+ 0,
+ v2d->mask.xmin + category_tabs_width,
+ rct->ymin);
}
#ifdef USE_FLAT_INACTIVE
/* draw line between inactive tabs */
if (is_active == false && is_active_prev == false && pc_dyn->prev) {
- glColor3ubv(theme_col_tab_divider);
- glRecti(v2d->mask.xmin + (category_tabs_width / 5),
- rct->ymax + px,
- (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
- rct->ymax + (px * 3));
+ immUniformColor3ubv(theme_col_tab_divider);
+ immRecti(pos, v2d->mask.xmin + (category_tabs_width / 5),
+ rct->ymax + px,
+ (v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
+ rct->ymax + (px * 3));
}
is_active_prev = is_active;
#endif
+ immUnbindProgram();
/* not essential, but allows events to be handled right up until the region edge [#38171] */
pc_dyn->rect.xmin = v2d->mask.xmin;
diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c
index b78fa0706c0..c5557a400ae 100644
--- a/source/blender/editors/interface/interface_regions.c
+++ b/source/blender/editors/interface/interface_regions.c
@@ -1697,6 +1697,28 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar)
UI_block_draw(C, block);
}
+/**
+ * Use to refresh centered popups on screen resizing (for splash).
+ */
+static void ui_block_region_popup_window_listener(
+ bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+{
+ switch (wmn->category) {
+ case NC_WINDOW:
+ {
+ switch (wmn->action) {
+ case NA_EDITED:
+ {
+ /* window resize */
+ ED_region_tag_refresh_ui(ar);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
+
static void ui_popup_block_clip(wmWindow *window, uiBlock *block)
{
uiBut *bt;
@@ -2008,6 +2030,11 @@ uiPopupBlockHandle *ui_popup_block_create(
block = ui_popup_block_refresh(C, handle, butregion, but);
handle = block->handle;
+ /* keep centered on window resizing */
+ if ((block->bounds_type == UI_BLOCK_BOUNDS_POPUP_CENTER) && handle->can_refresh) {
+ type.listener = ui_block_region_popup_window_listener;
+ }
+
return handle;
}
@@ -3290,7 +3317,7 @@ void UI_popup_block_invoke(bContext *C, uiBlockCreateFunc func, void *arg)
UI_popup_block_invoke_ex(C, func, arg, NULL, WM_OP_INVOKE_DEFAULT);
}
-void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg)
+void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, uiBlockCancelFunc cancel_func, void *arg, wmOperator *op)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
@@ -3299,6 +3326,7 @@ void UI_popup_block_ex(bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc po
handle->popup = true;
handle->retvalue = 1;
+ handle->popup_op = op;
handle->popup_arg = arg;
handle->popup_func = popup_func;
handle->cancel_func = cancel_func;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 2cdcf7a604d..e3a71feb1a9 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -58,6 +58,8 @@
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_idcode.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_main.h"
@@ -429,7 +431,8 @@ static void template_ID(
but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, width, height,
TIP_(template_id_browse_tip(type)));
if (use_preview_icon) {
- ui_def_but_icon(but, ui_id_icon_get(C, id, use_big_size), UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+ int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type);
+ ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
}
else {
ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON);
@@ -1991,6 +1994,7 @@ static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
case UICURVE_FUNC_HANDLE_AUTO_ANIM: /* set auto-clamped */
curvemap_handle_set(cuma, HD_AUTO_ANIM);
curvemapping_changed(cumap, false);
+ break;
case UICURVE_FUNC_EXTEND_HOZ: /* extend horiz */
cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
curvemapping_changed(cumap, false);
@@ -3732,6 +3736,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
if (propptr.data) {
uiBut *but = uiLayoutGetBlock(layout)->buttons.last;
+ WM_operator_properties_sanitize(&propptr, false);
template_keymap_item_properties(layout, NULL, &propptr);
/* attach callbacks to compensate for missing properties update,
@@ -3748,6 +3753,60 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
}
}
+/********************************* Overrides *************************************/
+
+void uiTemplateOverrideProperty(uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr, const char *name, const char *custom_template)
+{
+ bool is_set = false;
+ uiLayout *row, *col;
+
+ PointerRNA *ptr;
+ PropertyRNA *prop;
+
+ IDProperty *collection_props = collection_props_ptr->data;
+
+ if (IDP_GetPropertyFromGroup(collection_props, name)) {
+ prop = RNA_struct_find_property(collection_props_ptr, name);
+ ptr = collection_props_ptr;
+ is_set = RNA_property_is_set(ptr, prop);
+ }
+ else {
+ /* property doesn't exist yet */
+ prop = RNA_struct_find_property(scene_props_ptr, name);
+ ptr = scene_props_ptr;
+ }
+
+ row = uiLayoutRow(layout, false);
+ col = uiLayoutColumn(row, false);
+
+ uiLayoutSetEnabled(col, is_set);
+
+ if (custom_template && STREQ(custom_template, "icon_view")) {
+ uiTemplateIconView(col, ptr, name, false, 5.0f);
+ }
+ else {
+ uiItemFullR(col, ptr, prop, -1, 0, 0, NULL, ICON_NONE);
+ }
+
+ col = uiLayoutColumn(row, false);
+ uiBut *but;
+ uiBlock *block = uiLayoutGetBlock(col);
+ UI_block_emboss_set(block, UI_EMBOSS_NONE);
+
+ if (is_set) {
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unuse_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ }
+ else {
+ but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_use_property_button", WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
+ /* XXX - Using existing data struct to pass another RNAPointer */
+ but->rnasearchpoin = *scene_props_ptr;
+ }
+
+ but->rnapoin = *collection_props_ptr;
+ but->rnaprop = prop;
+ UI_block_emboss_set(block, UI_EMBOSS);
+}
+
/********************************* Color management *************************************/
void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname)
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index df6f098ee81..636b7e4e9ce 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -127,12 +127,10 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind
break;
case PROP_POINTER:
{
- PointerRNA pptr;
-
- pptr = RNA_property_pointer_get(ptr, prop);
- if (!pptr.type)
- pptr.type = RNA_property_pointer_type(ptr, prop);
- icon = RNA_struct_ui_icon(pptr.type);
+ if (icon == 0) {
+ PointerRNA pptr = RNA_property_pointer_get(ptr, prop);
+ icon = RNA_struct_ui_icon(pptr.type ? pptr.type : RNA_property_pointer_type(ptr, prop));
+ }
if (icon == ICON_DOT)
icon = 0;
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index ff4762ccc6a..05916bd2e6a 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -47,7 +47,6 @@
#include "RNA_access.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
@@ -59,6 +58,7 @@
#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#ifdef WITH_INPUT_IME
# include "WM_types.h"
@@ -187,28 +187,34 @@ static const unsigned int check_tria_face[4][3] = {
/* ************************************************* */
-void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3)
+void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3,
+ const float color[4])
{
float tri_arr[3][2] = {{x1, y1}, {x2, y2}, {x3, y3}};
- float color[4];
- int j;
-
+ float draw_color[4];
+
+ copy_v4_v4(draw_color, color);
+ draw_color[3] *= 0.125f;
+
glEnable(GL_BLEND);
- glGetFloatv(GL_CURRENT_COLOR, color);
- color[3] *= 0.125f;
- glColor4fv(color);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tri_arr);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4fv(draw_color);
+ immBegin(GL_TRIANGLES, 3 * WIDGET_AA_JITTER);
/* for each AA step */
- for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
- glDrawArrays(GL_TRIANGLES, 0, 3);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ for (int j = 0; j < WIDGET_AA_JITTER; j++) {
+ immVertex2f(pos, tri_arr[0][0] + jit[j][0], tri_arr[0][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[1][0] + jit[j][0], tri_arr[1][1] + jit[j][1]);
+ immVertex2f(pos, tri_arr[2][0] + jit[j][0], tri_arr[2][1] + jit[j][1]);
}
- glDisableClientState(GL_VERTEX_ARRAY);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -227,9 +233,9 @@ void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float m
draw_color[3] *= 0.125f;
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+ gpuTranslate2fv(jit[j]);
UI_draw_roundbox_gl_mode(mode, minx, miny, maxx, maxy, rad, draw_color);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ gpuTranslate2f(-jit[j][0], -jit[j][1]);
}
glDisable(GL_BLEND);
@@ -539,12 +545,27 @@ static void widget_scroll_circle(uiWidgetTrias *tria, const rcti *rect, float tr
scroll_circle_face, ARRAY_SIZE(scroll_circle_face));
}
-static void widget_trias_draw(uiWidgetTrias *tria)
+static void widget_trias_draw(uiWidgetTrias *tria, unsigned int pos)
+{
+ immBegin(GL_TRIANGLES, tria->tot * 3);
+ for (int i = 0; i < tria->tot; ++i)
+ for (int j = 0; j < 3; ++j)
+ immVertex2fv(pos, tria->vec[tria->index[i][j]]);
+ immEnd();
+}
+
+static void widget_draw_vertex_buffer(unsigned int pos, unsigned int col, int mode,
+ const float quads_pos[WIDGET_SIZE_MAX][2],
+ const unsigned char quads_col[WIDGET_SIZE_MAX][4],
+ unsigned int totvert)
{
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, tria->vec);
- glDrawElements(GL_TRIANGLES, tria->tot * 3, GL_UNSIGNED_INT, tria->index);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immBegin(mode, totvert);
+ for (int i = 0; i < totvert; ++i) {
+ if (quads_col)
+ immAttrib4ubv(col, quads_col[i]);
+ immVertex2fv(pos, quads_pos[i]);
+ }
+ immEnd();
}
static void widget_menu_trias(uiWidgetTrias *tria, const rcti *rect)
@@ -633,21 +654,18 @@ static void widget_verts_to_triangle_strip_open(uiWidgetBase *wtb, const int tot
}
}
-static void widgetbase_outline(uiWidgetBase *wtb)
+static void widgetbase_outline(uiWidgetBase *wtb, unsigned int pos)
{
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
widget_verts_to_triangle_strip(wtb, wtb->totvert, triangle_strip);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
}
static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
{
int j, a;
-
+
glEnable(GL_BLEND);
/* backdrop non AA */
@@ -657,78 +675,76 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
float inner_v_half[WIDGET_SIZE_MAX][2];
float x_mid = 0.0f; /* used for dumb clamping of values */
- /* dark checkers */
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
- /* light checkers */
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
+ /* checkers */
+ immUniform4f("color1", UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_DARK / 255.0f, 1.0f);
+ immUniform4f("color2", UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 1.0f);
+ immUniform1i("size", 8);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUnbindProgram();
/* alpha fill */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)wcol->inner);
- glColor4ubv((unsigned char *)wcol->inner);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (a = 0; a < wtb->totvert; a++) {
x_mid += wtb->inner_v[a][0];
}
x_mid /= wtb->totvert;
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
/* 1/2 solid color */
- glColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
+ immUniformColor4ub(wcol->inner[0], wcol->inner[1], wcol->inner[2], 255);
for (a = 0; a < wtb->totvert; a++) {
inner_v_half[a][0] = MIN2(wtb->inner_v[a][0], x_mid);
inner_v_half[a][1] = wtb->inner_v[a][1];
}
- glVertexPointer(2, GL_FLOAT, 0, inner_v_half);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, inner_v_half, NULL, wtb->totvert);
+
+ immUnbindProgram();
}
else {
/* simple fill */
- glColor4ubv((unsigned char *)wcol->inner);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)wcol->inner);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_FAN, wtb->inner_v, NULL, wtb->totvert);
+
+ immUnbindProgram();
}
}
else {
char col1[4], col2[4];
- unsigned char col_array[WIDGET_SIZE_MAX * 4];
- unsigned char *col_pt = col_array;
-
+ unsigned char col_array[WIDGET_SIZE_MAX][4];
+ unsigned char *col_pt = &col_array[0][0];
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
shadecolors4(col1, col2, wcol->inner, wcol->shadetop, wcol->shadedown);
for (a = 0; a < wtb->totvert; a++, col_pt += 4) {
round_box_shade_col4_r(col_pt, col1, col2, wtb->inner_uv[a][wtb->draw_shadedir ? 1 : 0]);
}
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, wtb->inner_v);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, col_array);
- glDrawArrays(GL_POLYGON, 0, wtb->totvert);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
+ widget_draw_vertex_buffer(pos, col, GL_TRIANGLE_FAN, wtb->inner_v, col_array, wtb->totvert);
+ immUnbindProgram();
}
}
-
+
/* for each AA step */
if (wtb->draw_outline) {
float triangle_strip[WIDGET_SIZE_MAX * 2 + 2][2]; /* + 2 because the last pair is wrapped */
@@ -747,52 +763,55 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol)
UI_GetThemeColor4ubv(TH_WIDGET_EMBOSS, emboss);
}
- glEnableClientState(GL_VERTEX_ARRAY);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+ gpuTranslate2fv(jit[j]);
/* outline */
- glColor4ubv(tcol);
+ immUniformColor4ubv(tcol);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->totvert * 2 + 2);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, wtb->totvert * 2 + 2);
/* emboss bottom shadow */
if (wtb->draw_emboss) {
if (emboss[3]) {
- glColor4ubv(emboss);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip_emboss);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, wtb->halfwayvert * 2);
+ immUniformColor4ubv(emboss);
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip_emboss, NULL, wtb->halfwayvert * 2);
}
}
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ gpuTranslate2f(-jit[j][0], -jit[j][1]);
}
-
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
-
+
/* decoration */
if (wtb->tria1.tot || wtb->tria2.tot) {
const unsigned char tcol[4] = {wcol->item[0],
wcol->item[1],
wcol->item[2],
(unsigned char)((float)wcol->item[3] / WIDGET_AA_JITTER)};
- glColor4ubv(tcol);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(tcol);
/* for each AA step */
for (j = 0; j < WIDGET_AA_JITTER; j++) {
- glTranslate2fv(jit[j]);
+ gpuTranslate2fv(jit[j]);
if (wtb->tria1.tot)
- widget_trias_draw(&wtb->tria1);
+ widget_trias_draw(&wtb->tria1, pos);
if (wtb->tria2.tot)
- widget_trias_draw(&wtb->tria2);
+ widget_trias_draw(&wtb->tria2, pos);
- glTranslatef(-jit[j][0], -jit[j][1], 0.0f);
+ gpuTranslate2f(-jit[j][0], -jit[j][1]);
}
+
+ immUnbindProgram();
}
glDisable(GL_BLEND);
@@ -876,21 +895,18 @@ static void widget_draw_icon(
float ofs = 1.0f / aspect;
if (but->drawflag & UI_BUT_ICON_LEFT) {
- if (but->block->flag & UI_BLOCK_LOOP) {
- if (but->type == UI_BTYPE_SEARCH_MENU)
- xs = rect->xmin + 4.0f * ofs;
- else
- xs = rect->xmin + ofs;
- }
- else {
+ /* special case - icon_only pie buttons */
+ if (ui_block_is_pie_menu(but->block) && but->type != UI_BTYPE_MENU && but->str && but->str[0] == '\0')
+ xs = rect->xmin + 2.0f * ofs;
+ else if (but->dt == UI_EMBOSS_NONE || but->type == UI_BTYPE_LABEL)
+ xs = rect->xmin + 2.0f * ofs;
+ else
xs = rect->xmin + 4.0f * ofs;
- }
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
}
else {
xs = (rect->xmin + rect->xmax - height) / 2.0f;
- ys = (rect->ymin + rect->ymax - height) / 2.0f;
}
+ ys = (rect->ymin + rect->ymax - height) / 2.0f;
/* force positions to integers, for zoom levels near 1. draws icons crisp. */
if (aspect > 0.95f && aspect < 1.05f) {
@@ -1366,11 +1382,16 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
selwidth_draw = BLF_width(fstyle->uifont_id, drawstr + but->ofs, but->selend - but->ofs);
- glColor4ubv((unsigned char *)wcol->item);
- glRecti(rect->xmin + selsta_draw,
- rect->ymin + 2,
- min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
- rect->ymax - 2);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ubv((unsigned char *)wcol->item);
+ immRecti(pos, rect->xmin + selsta_draw,
+ rect->ymin + 2,
+ min_ii(rect->xmin + selwidth_draw, rect->xmax - 2),
+ rect->ymax - 2);
+
+ immUnbindProgram();
}
}
@@ -1393,13 +1414,18 @@ static void widget_draw_text(uiFontStyle *fstyle, uiWidgetColors *wcol, uiBut *b
t = 0;
}
- glColor3f(0.2, 0.6, 0.9);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(0.2f, 0.6f, 0.9f);
tx = rect->xmin + t + 2;
ty = rect->ymin + 2;
/* draw cursor */
- glRecti(rect->xmin + t, ty, tx, rect->ymax - 2);
+ immRecti(pos, rect->xmin + t, ty, tx, rect->ymax - 2);
+
+ immUnbindProgram();
}
#ifdef WITH_INPUT_IME
@@ -1560,11 +1586,15 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
/* Icons on the left with optional text label on the right */
else if (but->flag & UI_HAS_ICON || show_menu_icon) {
const BIFIconID icon = (but->flag & UI_HAS_ICON) ? but->icon + but->iconadd : ICON_NONE;
- const float icon_size = ICON_SIZE_FROM_BUTRECT(rect);
+ const float icon_size = ICON_DEFAULT_WIDTH_SCALE;
/* menu item - add some more padding so menus don't feel cramped. it must
* be part of the button so that this area is still clickable */
- if (ui_block_is_menu(but->block))
+ if (ui_block_is_pie_menu(but->block)) {
+ if (but->dt == UI_EMBOSS_RADIAL)
+ rect->xmin += 0.3f * U.widget_unit;
+ }
+ else if (ui_block_is_menu(but->block))
rect->xmin += 0.3f * U.widget_unit;
widget_draw_icon(but, icon, alpha, rect, show_menu_icon);
@@ -1576,10 +1606,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
}
}
- if (but->drawflag & UI_BUT_TEXT_NO_MARGIN) {
- /* skip */
- }
- else if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
+ if (but->editstr || (but->drawflag & UI_BUT_TEXT_LEFT)) {
rect->xmin += (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect;
}
else if ((but->drawflag & UI_BUT_TEXT_RIGHT)) {
@@ -1593,7 +1620,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f);
if (extra_icon_type == UI_BUT_ICONEXTRA_CLEAR) {
- widget_draw_icon(but, ICON_X, alpha, &temp, false);
+ widget_draw_icon(but, ICON_PANEL_CLOSE, alpha, &temp, false);
}
else if (extra_icon_type == UI_BUT_ICONEXTRA_EYEDROPPER) {
widget_draw_icon(but, ICON_EYEDROPPER, alpha, &temp, false);
@@ -1629,6 +1656,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB
widget_draw_text(fstyle, wcol, but, rect);
ui_but_text_password_hide(password_str, but, true);
+
+ /* if a widget uses font shadow it has to be deactivated now */
+ BLF_disable(fstyle->uifont_id, BLF_SHADOW);
}
#undef UI_TEXT_CLIP_MARGIN
@@ -1887,6 +1917,19 @@ static struct uiWidgetColors wcol_list_item = {
0, 0
};
+struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255},
+ {114, 114, 114, 255},
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255},
+ {0, 0, 0, 255},
+
+ 0,
+ 0, 0
+};
+
/* free wcol struct to play with */
static struct uiWidgetColors wcol_tmp = {
{0, 0, 0, 255},
@@ -1909,6 +1952,7 @@ void ui_widget_color_init(ThemeUI *tui)
tui->wcol_tool = wcol_tool;
tui->wcol_text = wcol_text;
tui->wcol_radio = wcol_radio;
+ tui->wcol_tab = wcol_tab;
tui->wcol_option = wcol_option;
tui->wcol_toggle = wcol_toggle;
tui->wcol_num = wcol_num;
@@ -2167,23 +2211,24 @@ static void widget_softshadow(const rcti *rect, int roundboxalign, const float r
/* we draw a number of increasing size alpha quad strips */
alphastep = 3.0f * btheme->tui.menu_shadow_fac / radout;
-
- glEnableClientState(GL_VERTEX_ARRAY);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
for (step = 1; step <= (int)radout; step++) {
float expfac = sqrtf(step / radout);
round_box_shadow_edges(wtb.outer_v, &rect1, radin, UI_CNR_ALL, (float)step);
- glColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
+ immUniformColor4f(0.0f, 0.0f, 0.0f, alphastep * (1.0f - expfac));
widget_verts_to_triangle_strip(&wtb, totvert, triangle_strip);
- glVertexPointer(2, GL_FLOAT, 0, triangle_strip);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, totvert * 2); /* add + 2 for getting a complete soft rect. Now it skips top edge to allow transparent menus */
+ widget_draw_vertex_buffer(pos, 0, GL_TRIANGLE_STRIP, triangle_strip, NULL, totvert * 2);
}
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int direction)
@@ -2220,20 +2265,21 @@ static void widget_menu_back(uiWidgetColors *wcol, rcti *rect, int flag, int dir
static void ui_hsv_cursor(float x, float y)
{
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
-
- glColor3f(1.0f, 1.0f, 1.0f);
- glutil_draw_filled_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 8);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
+ imm_draw_filled_circle(pos, x, y, 3.0f * U.pixelsize, 8);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glColor3f(0.0f, 0.0f, 0.0f);
- glutil_draw_lined_arc(0.0f, M_PI * 2.0, 3.0f * U.pixelsize, 12);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ imm_draw_lined_circle(pos, x, y, 3.0f * U.pixelsize, 12);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
+
+ immUnbindProgram();
}
void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect,
@@ -2314,9 +2360,9 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
ui_color_picker_to_rgb(0.0f, 0.0f, hsv[2], colcent, colcent + 1, colcent + 2);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
@@ -2351,11 +2397,11 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
immUniformColor3ubv((unsigned char *)wcol->outline);
imm_draw_lined_circle(pos, centx, centy, radius, tot);
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- immUnbindProgram();
-
/* cursor */
float xpos, ypos;
ui_hsvcircle_pos_from_vals(but, rect, hsvo, &xpos, &ypos);
@@ -2368,7 +2414,8 @@ static void ui_draw_but_HSVCIRCLE(uiBut *but, uiWidgetColors *wcol, const rcti *
void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, const float alpha)
{
/* allows for 4 steps (red->yellow) */
- const float color_step = 1.0f / 48.0f;
+ const int steps = 48;
+ const float color_step = 1.0f / steps;
int a;
float h = hsv[0], s = hsv[1], v = hsv[2];
float dx, dy, sx1, sx2, sy;
@@ -2422,9 +2469,14 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
copy_v3_v3(col1[3], col1[2]);
break;
}
-
+
/* old below */
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+ immBegin(GL_TRIANGLES, steps * 3 * 6);
for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */
const float dx_next = dx + color_step;
@@ -2482,22 +2534,29 @@ void ui_draw_gradient(const rcti *rect, const float hsv[3], const int type, cons
sy = rect->ymin;
dy = (float)BLI_rcti_size_y(rect) / 3.0f;
- glBegin(GL_QUADS);
for (a = 0; a < 3; a++, sy += dy) {
- glColor4f(col0[a][0], col0[a][1], col0[a][2], alpha);
- glVertex2f(sx1, sy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
- glColor4f(col1[a][0], col1[a][1], col1[a][2], alpha);
- glVertex2f(sx2, sy);
+ immAttrib4f(col, col1[a][0], col1[a][1], col1[a][2], alpha);
+ immVertex2f(pos, sx2, sy);
+
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
- glVertex2f(sx2, sy + dy);
+ immAttrib4f(col, col0[a][0], col0[a][1], col0[a][2], alpha);
+ immVertex2f(pos, sx1, sy);
+
+ immAttrib4f(col, col1[a + 1][0], col1[a + 1][1], col1[a + 1][2], alpha);
+ immVertex2f(pos, sx2, sy + dy);
- glColor4f(col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
- glVertex2f(sx1, sy + dy);
+ immAttrib4f(col, col0[a + 1][0], col0[a + 1][1], col0[a + 1][2], alpha);
+ immVertex2f(pos, sx1, sy + dy);
}
- glEnd();
}
+ immEnd();
+
+ immUnbindProgram();
}
bool ui_but_is_colorpicker_display_space(uiBut *but)
@@ -2573,8 +2632,11 @@ static void ui_draw_but_HSVCUBE(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
/* outline */
- glColor3ub(0, 0, 0);
- fdrawbox((rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(0, 0, 0);
+ imm_draw_line_box(pos, (rect->xmin), (rect->ymin), (rect->xmax), (rect->ymax));
+ immUnbindProgram();
}
/* vertical 'value' slider, using new widget code */
@@ -2642,12 +2704,22 @@ static void ui_draw_separator(const rcti *rect, uiWidgetColors *wcol)
wcol->text[2],
30
};
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
glEnable(GL_BLEND);
- glColor4ubv(col);
+ immUniformColor4ubv(col);
glLineWidth(1.0f);
- sdrawline(rect->xmin, y, rect->xmax, y);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, rect->xmin, y);
+ immVertex2f(pos, rect->xmax, y);
+ immEnd();
+
glDisable(GL_BLEND);
+
+ immUnbindProgram();
}
/* ************ button callbacks, draw ***************** */
@@ -2719,11 +2791,14 @@ bool ui_link_bezier_points(const rcti *rect, float coord_array[][2], int resol)
}
#define LINK_RESOL 24
-void ui_draw_link_bezier(const rcti *rect)
+void ui_draw_link_bezier(const rcti *rect, const float color[4])
{
float coord_array[LINK_RESOL + 1][2];
if (ui_link_bezier_points(rect, coord_array, LINK_RESOL)) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
#if 0 /* unused */
/* we can reuse the dist variable here to increment the GL curve eval amount*/
const float dist = 1.0f / (float)LINK_RESOL;
@@ -2731,13 +2806,17 @@ void ui_draw_link_bezier(const rcti *rect)
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, coord_array);
- glDrawArrays(GL_LINE_STRIP, 0, LINK_RESOL + 1);
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUniformColor4fv(color);
+
+ immBegin(GL_LINE_STRIP, LINK_RESOL + 1);
+ for (int i = 0; i <= LINK_RESOL; ++i)
+ immVertex2fv(pos, coord_array[i]);
+ immEnd();
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
+
+ immUnbindProgram();
}
}
@@ -2919,15 +2998,16 @@ static void widget_link(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect, in
if (but->flag & UI_SELECT) {
rcti rectlink;
+ float color[4];
- UI_ThemeColor(TH_TEXT_HI);
+ UI_GetThemeColor4fv(TH_TEXT_HI, color);
rectlink.xmin = BLI_rcti_cent_x(rect);
rectlink.ymin = BLI_rcti_cent_y(rect);
rectlink.xmax = but->linkto[0];
rectlink.ymax = but->linkto[1];
- ui_draw_link_bezier(&rectlink);
+ ui_draw_link_bezier(&rectlink, color);
}
}
@@ -3079,13 +3159,18 @@ static void widget_swatch(uiBut *but, uiWidgetColors *wcol, rcti *rect, int stat
float bw = rgb_to_grayscale(col);
bw += (bw < 0.5f) ? 0.5f : -0.5f;
-
- glColor4f(bw, bw, bw, 1.0);
- glBegin(GL_TRIANGLES);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
- glVertex2f(rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
- glVertex2f(rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
- glEnd();
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(bw, bw, bw, 1.0f);
+ immBegin(GL_TRIANGLES, 3);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.9f * height);
+ immVertex2f(pos, rect->xmin + 0.1f * width, rect->ymin + 0.5f * height);
+ immVertex2f(pos, rect->xmin + 0.5f * width, rect->ymin + 0.9f * height);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -3381,12 +3466,50 @@ static void widget_roundbut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state),
widgetbase_draw(&wtb, wcol);
}
+static void widget_tab(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign)
+{
+ const uiStyle *style = UI_style_get();
+ const float rad = 0.15f * U.widget_unit;
+ const int fontid = style->widget.uifont_id;
+ const bool is_active = (but->flag & UI_SELECT);
+
+ uiWidgetBase wtb;
+ unsigned char theme_col_tab_highlight[3];
+
+ /* create outline highlight colors */
+ if (is_active) {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner_sel,
+ (unsigned char *)wcol->outline, 0.2f);
+ }
+ else {
+ interp_v3_v3v3_uchar(theme_col_tab_highlight, (unsigned char *)wcol->inner,
+ (unsigned char *)wcol->outline, 0.12f);
+ }
+
+ widget_init(&wtb);
+
+ /* half rounded */
+ round_box_edges(&wtb, roundboxalign, rect, rad);
+
+ /* draw inner */
+ wtb.draw_outline = 0;
+ widgetbase_draw(&wtb, wcol);
+
+ /* draw outline (3d look) */
+ ui_draw_but_TAB_outline(rect, rad, theme_col_tab_highlight, (unsigned char *)wcol->inner);
+
+ /* text shadow */
+ BLF_enable(fontid, BLF_SHADOW);
+ BLF_shadow(fontid, 3, (const float[4]){1.0f, 1.0f, 1.0f, 0.25f});
+ BLF_shadow_offset(fontid, 0, -1);
+}
+
static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *wt, rcti *rect)
{
uiWidgetBase wtb;
const float rad = 0.25f * U.widget_unit;
unsigned char col[4];
-
+
/* state copy! */
wt->wcol = *(wt->wcol_theme);
@@ -3396,12 +3519,17 @@ static void widget_draw_extra_mask(const bContext *C, uiBut *but, uiWidgetType *
/* note: drawextra can change rect +1 or -1, to match round errors of existing previews */
but->block->drawextra(C, but->poin, but->block->drawextra_arg1, but->block->drawextra_arg2, rect);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* make mask to draw over image */
UI_GetThemeColor3ubv(TH_BACK, col);
- glColor3ubv(col);
-
+ immUniformColor3ubv(col);
+
round_box__edges(&wtb, UI_CNR_ALL, rect, 0.0f, rad);
- widgetbase_outline(&wtb);
+ widgetbase_outline(&wtb, pos);
+
+ immUnbindProgram();
}
/* outline */
@@ -3463,6 +3591,11 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type)
wt.draw = widget_roundbut;
break;
+ case UI_WTYPE_TAB:
+ wt.custom = widget_tab;
+ wt.wcol_theme = &btheme->tui.wcol_tab;
+ break;
+
case UI_WTYPE_TOOLTIP:
wt.wcol_theme = &btheme->tui.wcol_tooltip;
wt.draw = widget_menu_back;
@@ -3717,7 +3850,11 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
if (but->block->flag & UI_BLOCK_LOOP)
wt->wcol_theme = &btheme->tui.wcol_menu_back;
break;
-
+
+ case UI_BTYPE_TAB:
+ wt = widget_type(UI_WTYPE_TAB);
+ break;
+
case UI_BTYPE_BUT_TOGGLE:
case UI_BTYPE_TOGGLE:
case UI_BTYPE_TOGGLE_N:
@@ -3910,15 +4047,21 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect)
wt->draw(&wt->wcol, rect, 0, 0);
if (block) {
+ float draw_color[4];
+ unsigned char *color = (unsigned char *)wt->wcol.text;
+
+ draw_color[0] = ((float)color[0]) / 255.0f;
+ draw_color[1] = ((float)color[1]) / 255.0f;
+ draw_color[2] = ((float)color[2]) / 255.0f;
+ draw_color[3] = 1.0f;
+
if (block->flag & UI_BLOCK_CLIPTOP) {
/* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymax - 8, 't', draw_color);
}
if (block->flag & UI_BLOCK_CLIPBOTTOM) {
/* XXX no scaling for UI here yet */
- glColor3ubv((unsigned char *)wt->wcol.text);
- UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v');
+ UI_draw_icon_tri(BLI_rcti_cent_x(rect), rect->ymin + 10, 'v', draw_color);
}
}
}
@@ -3936,33 +4079,21 @@ static void draw_disk_shaded(
float y1, y2;
float fac;
unsigned char r_col[4];
+ unsigned int pos, col;
- glBegin(GL_TRIANGLE_STRIP);
-
- s = sinf(start);
- c = cosf(start);
-
- y1 = s * radius_int;
- y2 = s * radius_ext;
-
+ VertexFormat *format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
if (shaded) {
- fac = (y1 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
}
-
- glVertex2f(c * radius_int, s * radius_int);
-
- if (shaded) {
- fac = (y2 + radius_ext) * radius_ext_scale;
- round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)col1);
}
- glVertex2f(c * radius_ext, s * radius_ext);
- for (i = 1; i < subd; i++) {
+ immBegin(GL_TRIANGLE_STRIP, subd * 2);
+ for (i = 0; i < subd; i++) {
float a;
a = start + ((i) / (float)(subd - 1)) * angle;
@@ -3974,20 +4105,20 @@ static void draw_disk_shaded(
if (shaded) {
fac = (y1 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_int, s * radius_int);
+ immVertex2f(pos, c * radius_int, s * radius_int);
if (shaded) {
fac = (y2 + radius_ext) * radius_ext_scale;
round_box_shade_col4_r(r_col, col1, col2, fac);
-
- glColor4ubv(r_col);
+ immAttrib4ubv(col, r_col);
}
- glVertex2f(c * radius_ext, s * radius_ext);
+ immVertex2f(pos, c * radius_ext, s * radius_ext);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
void ui_draw_pie_center(uiBlock *block)
@@ -4006,8 +4137,8 @@ void ui_draw_pie_center(uiBlock *block)
float angle = atan2f(pie_dir[1], pie_dir[0]);
float range = (block->pie_data.flags & UI_PIE_DEGREES_RANGE_LARGE) ? M_PI_2 : M_PI_4;
- glPushMatrix();
- glTranslatef(cx, cy, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(cx, cy);
glEnable(GL_BLEND);
if (btheme->tui.wcol_pie_menu.shaded) {
@@ -4016,8 +4147,7 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner);
- draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(0.0f, (float)(M_PI * 2.0), pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner, NULL, false);
}
if (!(block->pie_data.flags & UI_PIE_INVALID_DIR)) {
@@ -4027,25 +4157,34 @@ void ui_draw_pie_center(uiBlock *block)
draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, col1, col2, true);
}
else {
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.inner_sel);
- draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, NULL, NULL, false);
+ draw_disk_shaded(angle - range / 2.0f, range, pie_radius_internal, pie_radius_external, subd, btheme->tui.wcol_pie_menu.inner_sel, NULL, false);
}
}
- glColor4ubv((GLubyte *)btheme->tui.wcol_pie_menu.outline);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_internal, subd);
- glutil_draw_lined_arc(0.0f, (float)M_PI * 2.0f, pie_radius_external, subd);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv((unsigned char *)btheme->tui.wcol_pie_menu.outline);
+
+ imm_draw_lined_circle(pos, 0.0f, 0.0f, pie_radius_internal, subd);
+ imm_draw_lined_circle(pos, 0.0f, 0.0f, pie_radius_external, subd);
+
+ immUnbindProgram();
if (U.pie_menu_confirm > 0 && !(block->pie_data.flags & (UI_PIE_INVALID_DIR | UI_PIE_CLICK_STYLE))) {
float pie_confirm_radius = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm);
float pie_confirm_external = U.pixelsize * (pie_radius_internal + U.pie_menu_confirm + 7.0f);
- glColor4ub(btheme->tui.wcol_pie_menu.text_sel[0], btheme->tui.wcol_pie_menu.text_sel[1], btheme->tui.wcol_pie_menu.text_sel[2], 64);
- draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, NULL, NULL, false);
+ const char col[4] = {btheme->tui.wcol_pie_menu.text_sel[0],
+ btheme->tui.wcol_pie_menu.text_sel[1],
+ btheme->tui.wcol_pie_menu.text_sel[2],
+ 64};
+
+ draw_disk_shaded(angle - range / 2.0f, range, pie_confirm_radius, pie_confirm_external, subd, col, NULL, false);
}
glDisable(GL_BLEND);
- glPopMatrix();
+ gpuPopMatrix();
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index bf7fc0b8bd5..4975445de49 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -168,9 +168,6 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo
case SPACE_CLIP:
ts = &btheme->tclip;
break;
- case SPACE_COLLECTIONS:
- ts = &btheme->tcollections;
- break;
default:
ts = &btheme->tv3d;
break;
@@ -1212,11 +1209,6 @@ void ui_theme_init_default(void)
rgba_char_args_set(btheme->tclip.strip_select, 0xff, 0x8c, 0x00, 0xff);
btheme->tclip.handle_vertex_size = 5;
ui_theme_space_init_handles_color(&btheme->tclip);
-
- /* space collection manager */
- btheme->tcollections = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
- rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
}
void ui_style_init_default(void)
@@ -1509,13 +1501,13 @@ void UI_GetThemeColorBlendShade3ubv(int colorid1, int colorid2, float fac, int o
cp2 = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid2);
CLAMP(fac, 0.0f, 1.0f);
- col[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
- col[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
- col[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
- CLAMP(col[0], 0, 255);
- CLAMP(col[1], 0, 255);
- CLAMP(col[2], 0, 255);
+ float blend[3];
+ blend[0] = offset + floorf((1.0f - fac) * cp1[0] + fac * cp2[0]);
+ blend[1] = offset + floorf((1.0f - fac) * cp1[1] + fac * cp2[1]);
+ blend[2] = offset + floorf((1.0f - fac) * cp1[2] + fac * cp2[2]);
+
+ F3TOCHAR3(blend, col);
}
void UI_GetThemeColorShade4ubv(int colorid, int offset, unsigned char col[4])
@@ -2862,10 +2854,22 @@ void init_userdef_do_versions(void)
* (keep this block even if it becomes empty).
*/
{
+ /* interface_widgets.c */
+ struct uiWidgetColors wcol_tab = {
+ {255, 255, 255, 255},
+ {83, 83, 83, 255},
+ {114, 114, 114, 255},
+ {90, 90, 90, 255},
+
+ {0, 0, 0, 255},
+ {0, 0, 0, 255},
+
+ 0,
+ 0, 0
+ };
+
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
- btheme->tcollections = btheme->tv3d;
- rgba_char_args_set_fl(btheme->tcollections.back, 0.42, 0.42, 0.42, 1.0);
- rgba_char_args_set(btheme->tcollections.hilite, 255, 140, 25, 255); /* selected files */
+ btheme->tui.wcol_tab = wcol_tab;
}
for (bTheme *btheme = U.themes.first; btheme; btheme = btheme->next) {
diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c
index bcac8d0b825..5a9a4ef49eb 100644
--- a/source/blender/editors/interface/view2d.c
+++ b/source/blender/editors/interface/view2d.c
@@ -50,11 +50,10 @@
#include "BKE_global.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
-#include "BIF_gl.h"
-
#include "BLF_api.h"
#include "ED_screen.h"
@@ -1139,7 +1138,7 @@ void UI_view2d_view_restore(const bContext *C)
int height = BLI_rcti_size_y(&ar->winrct) + 1;
wmOrtho2(0.0f, (float)width, 0.0f, (float)height);
- glLoadIdentity();
+ gpuLoadIdentity();
// ED_region_pixelspace(CTX_wm_region(C));
}
@@ -1468,9 +1467,9 @@ void UI_view2d_constant_grid_draw(View2D *v2d)
count_y = (v2d->cur.ymax - start_y) / step + 1;
if (count_x > 0 || count_y > 0) {
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
float theme_color[3];
UI_GetThemeColorShade3fv(TH_BACK, -10, theme_color);
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index a991f59e8e2..3f9eb33e239 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -124,9 +124,9 @@ static int wm_alembic_export_exec(bContext *C, wmOperator *op)
.use_subdiv_schema = RNA_boolean_get(op->ptr, "subdiv_schema"),
.compression_type = RNA_enum_get(op->ptr, "compression_type"),
.packuv = RNA_boolean_get(op->ptr, "packuv"),
- .triangulate = RNA_boolean_get(op->ptr, "triangulate"),
- .quad_method = RNA_enum_get(op->ptr, "quad_method"),
- .ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
+ .triangulate = RNA_boolean_get(op->ptr, "triangulate"),
+ .quad_method = RNA_enum_get(op->ptr, "quad_method"),
+ .ngon_method = RNA_enum_get(op->ptr, "ngon_method"),
.global_scale = RNA_float_get(op->ptr, "global_scale"),
};
diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c
index baae92f962e..35d7c4f7083 100644
--- a/source/blender/editors/io/io_collada.c
+++ b/source/blender/editors/io/io_collada.c
@@ -97,7 +97,10 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
int use_blender_profile;
int sort_by_name;
int export_transformation_type;
+
int open_sim;
+ int limit_precision;
+ int keep_bind_info;
int export_count;
@@ -148,11 +151,15 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection");
open_sim = RNA_boolean_get(op->ptr, "open_sim");
+ limit_precision = RNA_boolean_get(op->ptr, "limit_precision");
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
/* get editmode results */
ED_object_editmode_load(CTX_data_edit_object(C));
export_count = collada_export(CTX_data_scene(C),
+ CTX_data_scene_layer(C),
filepath,
apply_modifiers,
export_mesh_type,
@@ -172,7 +179,11 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
use_blender_profile,
sort_by_name,
export_transformation_type,
- open_sim);
+
+ open_sim,
+ limit_precision,
+ keep_bind_info
+ );
if (export_count == 0) {
BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file");
@@ -256,11 +267,11 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
uiItemL(row, IFACE_("Collada Options:"), ICON_MODIFIER);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "triangulate", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "use_object_instantiation", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
- uiItemR(row, imfptr, "use_blender_profile", 0, NULL, ICON_NONE);
+ uiItemR(row, imfptr, "use_blender_profile", 1, NULL, ICON_NONE);
row = uiLayoutRow(box, false);
split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT);
@@ -270,6 +281,12 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE);
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "limit_precision", 0, NULL, ICON_NONE);
+
}
static void wm_collada_export_draw(bContext *UNUSED(C), wmOperator *op)
@@ -296,6 +313,8 @@ static bool wm_collada_export_check(bContext *UNUSED(C), wmOperator *op)
void WM_OT_collada_export(wmOperatorType *ot)
{
+ struct StructRNA *func = ot->srna;
+
static EnumPropertyItem prop_bc_export_mesh_type[] = {
{BC_MESH_TYPE_VIEW, "view", 0, "View", "Apply modifier's view settings"},
{BC_MESH_TYPE_RENDER, "render", 0, "Render", "Apply modifier's render settings"},
@@ -325,65 +344,72 @@ void WM_OT_collada_export(wmOperatorType *ot)
ot, FILE_TYPE_FOLDER | FILE_TYPE_COLLADA, FILE_BLENDER, FILE_SAVE,
WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
- RNA_def_boolean(ot->srna,
+ RNA_def_boolean(func,
"apply_modifiers", 0, "Apply Modifiers",
"Apply modifiers to exported mesh (non destructive))");
- RNA_def_int(ot->srna, "export_mesh_type", 0, INT_MIN, INT_MAX,
+ RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
"Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
- RNA_def_enum(ot->srna, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
+ RNA_def_enum(func, "export_mesh_type_selection", prop_bc_export_mesh_type, 0,
"Resolution", "Modifier resolution for export");
- RNA_def_boolean(ot->srna, "selected", 0, "Selection Only",
+ RNA_def_boolean(func, "selected", 0, "Selection Only",
"Export only selected elements");
- RNA_def_boolean(ot->srna, "include_children", 0, "Include Children",
+ RNA_def_boolean(func, "include_children", 0, "Include Children",
"Export all children of selected objects (even if not selected)");
- RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
+ RNA_def_boolean(func, "include_armatures", 0, "Include Armatures",
"Export related armatures (even if not selected)");
- RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys",
+ RNA_def_boolean(func, "include_shapekeys", 1, "Include Shape Keys",
"Export all Shape Keys from Mesh Objects");
- RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only",
+ RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only",
"Only export deforming bones with armatures");
- RNA_def_boolean(ot->srna, "active_uv_only", 0, "Only Selected UV Map",
+ RNA_def_boolean(func, "active_uv_only", 0, "Only Selected UV Map",
"Export only the selected UV Map");
- RNA_def_boolean(ot->srna, "include_uv_textures", 0, "Include UV Textures",
+ RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures",
"Export textures assigned to the object UV Maps");
- RNA_def_boolean(ot->srna, "include_material_textures", 0, "Include Material Textures",
+ RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures",
"Export textures assigned to the object Materials");
- RNA_def_boolean(ot->srna, "use_texture_copies", 1, "Copy",
+ RNA_def_boolean(func, "use_texture_copies", 1, "Copy",
"Copy textures to same folder where the .dae file is exported");
- RNA_def_boolean(ot->srna, "triangulate", 1, "Triangulate",
+ RNA_def_boolean(func, "triangulate", 1, "Triangulate",
"Export Polygons (Quads & NGons) as Triangles");
- RNA_def_boolean(ot->srna, "use_object_instantiation", 1, "Use Object Instances",
+ RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances",
"Instantiate multiple Objects from same Data");
- RNA_def_boolean(ot->srna, "use_blender_profile", 1, "Use Blender Profile",
+ RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile",
"Export additional Blender specific information (for material, shaders, bones, etc.)");
- RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name",
+ RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name",
"Sort exported data by Object name");
- RNA_def_int(ot->srna, "export_transformation_type", 0, INT_MIN, INT_MAX,
+ RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
"Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
- RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
+ RNA_def_enum(func, "export_transformation_type_selection", prop_bc_export_transformation_type, 0,
"Transform", "Transformation type for translation, scale and rotation");
- RNA_def_boolean(ot->srna, "open_sim", 0, "Export to SL/OpenSim",
+ RNA_def_boolean(func, "open_sim", 0, "Export to SL/OpenSim",
"Compatibility mode for SL, OpenSim and other compatible online worlds");
+
+ RNA_def_boolean(func, "limit_precision", 0,
+ "Limit Precision", "Reduce the precision of the exported data to 6 digits");
+
+ RNA_def_boolean(func, "keep_bind_info", 0,
+ "Keep Bind Info", "Store Bindpose information in custom bone properties for later use during Collada export");
+
}
@@ -395,7 +421,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
int find_chains;
int auto_connect;
int fix_orientation;
- int min_chain_length;
+ int min_chain_length;
+
+ int keep_bind_info;
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -407,6 +435,9 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
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");
+
+ keep_bind_info = RNA_boolean_get(op->ptr, "keep_bind_info");
+
min_chain_length = RNA_int_get(op->ptr, "min_chain_length");
RNA_string_get(op->ptr, "filepath", filename);
@@ -416,7 +447,8 @@ static int wm_collada_import_exec(bContext *C, wmOperator *op)
find_chains,
auto_connect,
fix_orientation,
- min_chain_length))
+ min_chain_length,
+ keep_bind_info) )
{
return OPERATOR_FINISHED;
}
@@ -453,6 +485,13 @@ static void uiCollada_importSettings(uiLayout *layout, PointerRNA *imfptr)
row = uiLayoutRow(box, false);
uiItemR(row, imfptr, "min_chain_length", 0, NULL, ICON_NONE);
+
+ box = uiLayoutBox(layout);
+ row = uiLayoutRow(box, false);
+
+ row = uiLayoutRow(box, false);
+ uiItemR(row, imfptr, "keep_bind_info", 0, NULL, ICON_NONE);
+
}
static void wm_collada_import_draw(bContext *UNUSED(C), wmOperator *op)
@@ -508,5 +547,9 @@ void WM_OT_collada_import(wmOperatorType *ot)
0,
INT_MAX);
+ RNA_def_boolean(ot->srna,
+ "keep_bind_info", 0, "Keep Bind Info",
+ "Store Bindpose information in custom bone properties for later use during Collada export");
+
}
#endif
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index 2b4f94a37ef..eb3721a7ed3 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -36,6 +36,7 @@
#include "BLI_math.h"
#include "BLI_rect.h"
#include "BLI_task.h"
+#include "BLI_listbase.h"
#include "BKE_context.h"
#include "BKE_mask.h"
@@ -48,10 +49,13 @@
#include "ED_clip.h"
#include "ED_mask.h" /* own include */
#include "ED_space_api.h"
-#include "BIF_gl.h"
+
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_draw.h"
+#include "GPU_shader.h"
+#include "GPU_matrix.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -93,40 +97,6 @@ static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline
r_rgb[3] = 255;
}
-#if 0
-static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
-{
- int i;
- MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
-
- if (!spline->tot_point)
- return;
-
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
-
- glColor3ub(0, 0, 0);
- glBegin(GL_LINES);
-
- for (i = 0; i < spline->tot_point; i++) {
- MaskSplinePoint *point = &points_array[i];
- BezTriple *bezt = &point->bezt;
-
- if (point->parent.id) {
- glVertex2f(bezt->vec[1][0],
- bezt->vec[1][1]);
-
- glVertex2f(bezt->vec[1][0] - point->parent.offset[0],
- bezt->vec[1][1] - point->parent.offset[1]);
- }
- }
-
- glEnd();
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
-}
-#endif
-
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
{
BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
@@ -134,46 +104,9 @@ static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float c
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
}
-static void draw_circle(const float x, const float y,
- const float size, const bool fill,
- const float xscale, const float yscale)
-{
- static GLuint wire_displist = 0;
- static GLuint fill_displist = 0;
- GLuint displist = fill ? fill_displist : wire_displist;
-
- /* Initialize round circle shape. */
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, fill ? GLU_FILL : GLU_SILHOUETTE);
- gluDisk(qobj, 0, 0.7, 8, 1);
- gluDeleteQuadric(qobj);
-
- glEndList();
-
- if (fill) {
- fill_displist = displist;
- }
- else {
- wire_displist = displist;
- }
- }
-
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * size, 1.0f / yscale * size, 1.0f);
- glCallList(displist);
- glPopMatrix();
-}
-
static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoint *point,
const eMaskWhichHandle which_handle, const int draw_type,
- const float handle_size, const float xscale, const float yscale,
+ const float handle_size,
const float point_pos[2], const float handle_pos[2])
{
const BezTriple *bezt = &point->bezt;
@@ -190,54 +123,70 @@ static void draw_single_handle(const MaskLayer *mask_layer, const MaskSplinePoin
return;
}
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ubv(rgb_gray);
+
/* this could be split into its own loop */
if (draw_type == MASK_DT_OUTLINE) {
- const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
- glLineWidth(3);
- glColor4ubv(rgb_gray);
- glBegin(GL_LINES);
- glVertex2fv(point_pos);
- glVertex2fv(handle_pos);
- glEnd();
+ glLineWidth(3.0f);
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
}
switch (handle_type) {
case HD_FREE:
- UI_ThemeColor(TH_HANDLE_FREE);
+ immUniformThemeColor(TH_HANDLE_FREE);
break;
case HD_AUTO:
- UI_ThemeColor(TH_HANDLE_AUTO);
+ immUniformThemeColor(TH_HANDLE_AUTO);
break;
case HD_ALIGN:
case HD_ALIGN_DOUBLESIDE:
- UI_ThemeColor(TH_HANDLE_ALIGN);
+ immUniformThemeColor(TH_HANDLE_ALIGN);
break;
}
- glLineWidth(1);
- glBegin(GL_LINES);
- glVertex2fv(point_pos);
- glVertex2fv(handle_pos);
- glEnd();
+ glLineWidth(1.0f);
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, point_pos);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+ immUnbindProgram();
/* draw handle points */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("size", handle_size);
+ immUniform1f("outlineWidth", 1.5f);
+
+ float point_color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* active color by default */
if (MASKPOINT_ISSEL_HANDLE(point, which_handle)) {
- if (point == mask_layer->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
- else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ if (point != mask_layer->act_point) {
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX_SELECT, point_color);
+ }
}
else {
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ UI_GetThemeColor3fv(TH_HANDLE_VERTEX, point_color);
}
- draw_circle(handle_pos[0], handle_pos[1], handle_size, false, xscale, yscale);
+ immUniform4fv("outlineColor", point_color);
+ immUniformColor3fvAlpha(point_color, 0.25f);
+
+ immBegin(PRIM_POINTS, 1);
+ immVertex2fv(pos, handle_pos);
+ immEnd();
+
+ immUnbindProgram();
}
/* return non-zero if spline is selected */
static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
- const char draw_flag, const char draw_type,
- const float xscale, const float yscale)
+ const char draw_flag, const char draw_type)
{
const bool is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
const bool is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH) != 0;
@@ -247,7 +196,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
SpaceClip *sc = CTX_wm_space_clip(C);
bool undistort = false;
- int i, handle_size, tot_feather_point;
+ int tot_feather_point;
float (*feather_points)[2], (*fp)[2];
float min[2], max[2];
@@ -258,22 +207,24 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
/* TODO, add this to sequence editor */
- handle_size = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
-
- glPointSize(handle_size);
+ float handle_size = 2.0f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) * U.pixelsize;
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+ immUniform1f("size", 0.7f * handle_size);
+
/* feather points */
feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
- for (i = 0; i < spline->tot_point; i++) {
+ for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
- int j;
-
- for (j = 0; j <= point->tot_uw; j++) {
+ for (int j = 0; j <= point->tot_uw; j++) {
float feather_point[2];
bool sel = false;
@@ -291,32 +242,32 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
if (sel) {
if (point == masklay->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
}
else {
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ immUniformThemeColor(TH_HANDLE_VERTEX);
}
- glBegin(GL_POINTS);
- glVertex2fv(feather_point);
- glEnd();
+ immBegin(PRIM_POINTS, 1);
+ immVertex2fv(pos, feather_point);
+ immEnd();
fp++;
}
}
MEM_freeN(feather_points);
+ immUnbindProgram();
+
if (is_smooth) {
glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
/* control points */
INIT_MINMAX2(min, max);
- for (i = 0; i < spline->tot_point; i++) {
+ for (int i = 0; i < spline->tot_point; i++) {
/* watch it! this is intentionally not the deform array, only check for sel */
MaskSplinePoint *point = &spline->points[i];
@@ -339,7 +290,7 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
mask_point_undistort_pos(sc, handle, handle);
}
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_STICK,
- draw_type, handle_size, xscale, yscale, vert, handle);
+ draw_type, handle_size, vert, handle);
}
else {
float handle_left[2], handle_right[2];
@@ -350,53 +301,62 @@ static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline
mask_point_undistort_pos(sc, handle_left, handle_left);
}
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_LEFT,
- draw_type, handle_size, xscale, yscale, vert, handle_left);
+ draw_type, handle_size, vert, handle_left);
draw_single_handle(masklay, point, MASK_WHICH_HANDLE_RIGHT,
- draw_type, handle_size, xscale, yscale, vert, handle_right);
+ draw_type, handle_size, vert, handle_right);
}
+ /* bind program in loop so it does not interfere with draw_single_handle */
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
+
/* draw CV point */
if (MASKPOINT_ISSEL_KNOT(point)) {
if (point == masklay->act_point)
- glColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
else
- UI_ThemeColor(TH_HANDLE_VERTEX_SELECT);
+ immUniformThemeColor(TH_HANDLE_VERTEX_SELECT);
}
else
- UI_ThemeColor(TH_HANDLE_VERTEX);
+ immUniformThemeColor(TH_HANDLE_VERTEX);
+
+ immBegin(PRIM_POINTS, 1);
+ immVertex2fv(pos, vert);
+ immEnd();
- glBegin(GL_POINTS);
- glVertex2fv(vert);
- glEnd();
+ immUnbindProgram();
minmax_v2v2_v2(min, max, vert);
}
+ if (is_smooth) {
+ glDisable(GL_LINE_SMOOTH);
+ }
+
if (is_spline_sel) {
- float x = (min[0] + max[0]) / 2.0f;
- float y = (min[1] + max[1]) / 2.0f;
- /* TODO(sergey): Remove hardcoded colors. */
+ float x = (min[0] + max[0]) * 0.5f;
+ float y = (min[1] + max[1]) * 0.5f;
+
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
+ immUniform1f("outlineWidth", 1.5f);
+
if (masklay->act_spline == spline) {
- glColor3ub(255, 255, 255);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
}
else {
- glColor3ub(255, 255, 0);
+ immUniformColor3f(1.0f, 1.0f, 0.0f);
}
- draw_circle(x, y, 6.0f, true, xscale, yscale);
+ immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ immUniform1f("size", 12.0f);
- glColor3ub(0, 0, 0);
- draw_circle(x, y, 6.0f, false, xscale, yscale);
- }
+ immBegin(PRIM_POINTS, 1);
+ immVertex2f(pos, x, y);
+ immEnd();
- if (is_smooth) {
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ immUnbindProgram();
}
}
-/* #define USE_XOR */
-
static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const bool is_active)
{
if (!is_active) {
@@ -410,13 +370,21 @@ static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char r
}
}
+static void mask_draw_array(unsigned int pos, PrimitiveType prim_type, const float (*points)[2], unsigned int vertex_ct)
+{
+ immBegin(prim_type, vertex_ct);
+ for (unsigned int i = 0; i < vertex_ct; ++i) {
+ immVertex2fv(pos, points[i]);
+ }
+ immEnd();
+}
+
static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point,
- const bool is_feather, const bool is_smooth, const bool is_active,
+ const bool is_feather, const bool is_active,
const unsigned char rgb_spline[4], const char draw_type)
{
- const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP;
+ const PrimitiveType draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? PRIM_LINE_LOOP : PRIM_LINE_STRIP;
const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
-// const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff};
unsigned char rgb_tmp[4];
SpaceClip *sc = CTX_wm_space_clip(C);
float (*points)[2] = orig_points;
@@ -425,65 +393,45 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
const bool undistort = sc->clip && (sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT);
if (undistort) {
- int i;
-
points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
- for (i = 0; i < tot_point; i++) {
+ for (int i = 0; i < tot_point; i++) {
mask_point_undistort_pos(sc, points[i], orig_points[i]);
}
}
}
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
switch (draw_type) {
case MASK_DT_OUTLINE:
- glLineWidth(3);
-
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- glColor4ubv(rgb_tmp);
-
- glDrawArrays(draw_method, 0, tot_point);
+ /* TODO(merwin): use fancy line shader here
+ * probably better with geometry shader (after core profile switch)
+ */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glLineWidth(1);
- mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- glColor4ubv(rgb_tmp);
- glDrawArrays(draw_method, 0, tot_point);
+ glLineWidth(3.0f);
- break;
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- case MASK_DT_DASH:
- default:
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
+ glLineWidth(1.0f);
-#ifdef USE_XOR
- glEnable(GL_COLOR_LOGIC_OP);
- glLogicOp(GL_OR);
-#endif
mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
- glColor4ubv(rgb_tmp);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
- glDrawArrays(draw_method, 0, tot_point);
-
-#ifdef USE_XOR
- glDisable(GL_COLOR_LOGIC_OP);
-#endif
- mask_color_active_tint(rgb_tmp, rgb_black, is_active);
- glColor4ubv(rgb_tmp);
- GPU_basic_shader_line_stipple(3, 0x5555);
- glDrawArrays(draw_method, 0, tot_point);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immUnbindProgram();
break;
-
case MASK_DT_BLACK:
case MASK_DT_WHITE:
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ glLineWidth(1.0f);
+
if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; }
else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
/* alpha values seem too low but gl draws many points that compensate for it */
@@ -496,26 +444,39 @@ static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*
rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
}
- if (is_smooth == false && is_feather) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- }
-
mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
- glColor4ubv(rgb_tmp);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, points);
- glDrawArrays(draw_method, 0, tot_point);
+ immUnbindProgram();
+ break;
- if (is_smooth == false && is_feather) {
- glDisable(GL_BLEND);
- }
+ case MASK_DT_DASH:
+ /* TODO(merwin): use dashed line shader here
+ * probably better with geometry shader (after core profile switch)
+ */
+#if 0
+ glLineWidth(1.0f);
+
+ GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ GPU_basic_shader_line_stipple(3, 0xAAAA);
+ mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ mask_color_active_tint(rgb_tmp, rgb_black, is_active);
+ immUniformColor4ubv(rgb_tmp);
+ GPU_basic_shader_line_stipple(3, 0x5555);
+ mask_draw_array(pos, draw_method, points, tot_point);
+
+ GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+#endif
break;
- }
- glDisableClientState(GL_VERTEX_ARRAY);
+ default:
+ BLI_assert(false);
+ }
if (points != orig_points)
MEM_freeN(points);
@@ -548,8 +509,6 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
if (is_smooth) {
glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, &tot_feather_point, resol, (is_fill != false));
@@ -557,26 +516,24 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
/* draw feather */
mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_smooth, is_active,
+ true, is_active,
rgb_tmp, draw_type);
if (!is_fill) {
-
const float *fp = &diff_points[0][0];
float *fp_feather = &feather_points[0][0];
- float tvec[2];
- int i;
BLI_assert(tot_diff_point == tot_feather_point);
- for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
+ for (int i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
+ float tvec[2];
sub_v2_v2v2(tvec, fp, fp_feather);
add_v2_v2v2(fp_feather, fp, tvec);
}
/* same as above */
mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
- true, is_smooth, is_active,
+ true, is_active,
rgb_tmp, draw_type);
}
@@ -585,21 +542,22 @@ static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline
/* draw main curve */
mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
mask_draw_curve_type(C, spline, diff_points, tot_diff_point,
- false, is_smooth, is_active,
+ false, is_active,
rgb_tmp, draw_type);
MEM_freeN(diff_points);
- if (draw_flag & MASK_DRAWFLAG_SMOOTH) {
+ if (is_smooth) {
glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
}
-
- (void)draw_type;
}
static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
- const int width, const int height, const float xscale, const float yscale)
+ const int width, const int height)
{
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GPU_enable_program_point_size();
+
MaskLayer *masklay;
int i;
@@ -616,11 +574,9 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
/* draw curve itself first... */
draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
-// draw_spline_parents(masklay, spline);
-
if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
/* ...and then handles over the curve so they're nicely visible */
- draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
}
/* show undeform for testing */
@@ -629,33 +585,29 @@ static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, c
spline->points_deform = NULL;
draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
-// draw_spline_parents(masklay, spline);
- draw_spline_points(C, masklay, spline, draw_flag, draw_type, xscale, yscale);
+ draw_spline_points(C, masklay, spline, draw_flag, draw_type);
spline->points_deform = back;
}
}
}
+
+ GPU_disable_program_point_size();
+ glDisable(GL_BLEND);
}
void ED_mask_draw(const bContext *C,
const char draw_flag, const char draw_type)
{
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
-
Mask *mask = CTX_data_edit_mask(C);
int width, height;
- float aspx, aspy;
- float xscale, yscale;
if (!mask)
return;
ED_mask_get_size(sa, &width, &height);
- ED_mask_get_aspect(sa, ar, &aspx, &aspy);
- UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
- draw_masklays(C, mask, draw_flag, draw_type, width, height, xscale * aspx, yscale * aspy);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
}
typedef struct ThreadedMaskRasterizeState {
@@ -802,28 +754,26 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
if (draw_flag & MASK_DRAWFLAG_OVERLAY) {
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
float *buffer = threaded_mask_rasterize(mask, width, height);
- int format;
- if (overlay_mode == MASK_OVERLAY_ALPHACHANNEL) {
- glColor3f(1.0f, 1.0f, 1.0f);
- format = GL_LUMINANCE;
- }
- else {
+ if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
/* More blending types could be supported in the future. */
glEnable(GL_BLEND);
- glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
- format = GL_ALPHA;
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
}
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
if (stabmat) {
- glMultMatrixf(stabmat);
+ gpuMultMatrix3D(stabmat); /* XXX make this a 2D matrix */
}
- glaDrawPixelsTex(0.0f, 0.0f, width, height, format, GL_FLOAT, GL_NEAREST, buffer);
- glPopMatrix();
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
+ immDrawPixelsTex(0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
+
+ gpuPopMatrix();
if (overlay_mode != MASK_OVERLAY_ALPHACHANNEL) {
glDisable(GL_BLEND);
@@ -833,27 +783,27 @@ void ED_mask_draw_region(Mask *mask, ARegion *ar,
}
/* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
- glPushMatrix();
+ gpuPushMatrix();
if (stabmat) {
- glMultMatrixf(stabmat);
+ gpuMultMatrix3D(stabmat); /* XXX make this a 2D matrix */
}
- glTranslatef(x + xofs, y + yofs, 0);
- glScalef(maxdim * zoomx, maxdim * zoomy, 0);
+ gpuTranslate2f(x + xofs, y + yofs);
+ gpuScale2f(maxdim * zoomx, maxdim * zoomy);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
}
/* draw! */
- draw_masklays(C, mask, draw_flag, draw_type, width, height, maxdim * zoomx, maxdim * zoomy);
+ draw_masklays(C, mask, draw_flag, draw_type, width, height);
if (do_draw_cb) {
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
}
- glPopMatrix();
+ gpuPopMatrix();
}
void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
@@ -862,25 +812,31 @@ void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra
MaskLayer *masklay = BKE_mask_layer_active(mask);
- glBegin(GL_LINES);
- glColor4ub(255, 175, 0, 255);
-
if (masklay) {
- MaskLayerShape *masklay_shape;
-
- for (masklay_shape = masklay->splines_shapes.first;
- masklay_shape;
- masklay_shape = masklay_shape->next)
- {
- int frame = masklay_shape->frame;
-
- /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
- int height = (frame == cfra) ? 22 : 10;
- int x = (frame - sfra) * framelen;
- glVertex2i(x, 0);
- glVertex2i(x, height);
+ unsigned int num_lines = BLI_listbase_count(&masklay->splines_shapes);
+
+ if (num_lines > 0) {
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ub(255, 175, 0, 255);
+
+ immBegin(PRIM_LINES, 2 * num_lines);
+
+ for (MaskLayerShape *masklay_shape = masklay->splines_shapes.first;
+ masklay_shape;
+ masklay_shape = masklay_shape->next)
+ {
+ int frame = masklay_shape->frame;
+
+ /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
+ int height = (frame == cfra) ? 22 : 10;
+ int x = (frame - sfra) * framelen;
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height);
+ }
+ immEnd();
+ immUnbindProgram();
}
}
-
- glEnd();
}
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index de93211bec4..49bfde77032 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -51,6 +51,7 @@
#include "mesh_intern.h" /* own include */
#include "tools/bmesh_intersect.h"
+#include "tools/bmesh_separate.h"
/* detect isolated holes and fill them */
@@ -137,6 +138,12 @@ enum {
ISECT_SEL_UNSEL = 1,
};
+enum {
+ ISECT_SEPARATE_ALL = 0,
+ ISECT_SEPARATE_CUT = 1,
+ ISECT_SEPARATE_NONE = 2,
+};
+
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
@@ -144,7 +151,9 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
BMesh *bm = em->bm;
const int mode = RNA_enum_get(op->ptr, "mode");
int (*test_fn)(BMFace *, void *);
- bool use_separate = RNA_boolean_get(op->ptr, "use_separate");
+ bool use_separate_all = false;
+ bool use_separate_cut = false;
+ const int separate_mode = RNA_enum_get(op->ptr, "separate_mode");
const float eps = RNA_float_get(op->ptr, "threshold");
bool use_self;
bool has_isect;
@@ -160,15 +169,38 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
break;
}
+ switch (separate_mode) {
+ case ISECT_SEPARATE_ALL:
+ use_separate_all = true;
+ break;
+ case ISECT_SEPARATE_CUT:
+ if (use_self == false) {
+ use_separate_cut = true;
+ }
+ else {
+ /* we could support this but would require more advanced logic inside 'BM_mesh_intersect'
+ * for now just separate all */
+ use_separate_all = true;
+ }
+ break;
+ default: /* ISECT_SEPARATE_NONE */
+ break;
+ }
has_isect = BM_mesh_intersect(
bm,
em->looptris, em->tottri,
test_fn, NULL,
- use_self, use_separate, true, true,
+ use_self, use_separate_all, true, true, true,
-1,
eps);
+ if (use_separate_cut) {
+ /* detach selected/un-selected faces */
+ BM_mesh_separate_faces(
+ bm,
+ BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
+ }
if (has_isect) {
edbm_intersect_select(em);
@@ -190,6 +222,16 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
{0, NULL, 0, NULL, NULL}
};
+ static EnumPropertyItem isect_separate_items[] = {
+ {ISECT_SEPARATE_ALL, "ALL", 0, "All",
+ "Separate all geometry from intersections"},
+ {ISECT_SEPARATE_CUT, "CUT", 0, "Cut",
+ "Cut into geometry keeping each side separate (Selected/Unselected only)"},
+ {ISECT_SEPARATE_NONE, "NONE", 0, "Merge",
+ "Merge all geometry from the intersection"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
/* identifiers */
ot->name = "Intersect (Knife)";
ot->description = "Cut an intersection into faces";
@@ -201,7 +243,7 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "mode", isect_mode_items, ISECT_SEL_UNSEL, "Source", "");
- RNA_def_boolean(ot->srna, "use_separate", true, "Separate", "");
+ RNA_def_enum(ot->srna, "separate_mode", isect_separate_items, ISECT_SEPARATE_CUT, "Separate Mode", "");
RNA_def_float_distance(ot->srna, "threshold", 0.000001f, 0.0, 0.01, "Merge threshold", "", 0.0, 0.001);
/* flags */
@@ -239,7 +281,7 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
bm,
em->looptris, em->tottri,
test_fn, NULL,
- false, false, true, true,
+ false, false, true, true, true,
boolean_operation,
eps);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 2250aaab310..a7fa5eb8138 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -54,10 +54,10 @@
#include "BKE_editmesh_bvh.h"
#include "BKE_report.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h" /* for paint cursor */
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_screen.h"
#include "ED_space_api.h"
@@ -1043,8 +1043,8 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
glPolygonOffset(1.0f, 1.0f);
- glPushMatrix();
- glMultMatrixf(kcd->ob->obmat);
+ gpuPushMatrix();
+ gpuMultMatrix3D(kcd->ob->obmat);
unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
@@ -1191,7 +1191,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -1418,7 +1418,7 @@ static bool bm_ray_cast_cb_elem_not_in_face_check(BMFace *f, void *user_data)
* intersecting faces matching this face (or connected when an vert/edge) will be ignored.
*/
static bool point_is_visible(
- KnifeTool_OpData *kcd, const float p[3], const float s[2], bglMats *mats,
+ KnifeTool_OpData *kcd, const float p[3], const float s[2],
BMElem *ele_test)
{
BMFace *f_hit;
@@ -1436,7 +1436,7 @@ static bool point_is_visible(
float view[3], p_ofs[3];
/* TODO: I think there's a simpler way to get the required raycast ray */
- ED_view3d_unproject(mats, view, s[0], s[1], 0.0f);
+ ED_view3d_unproject(kcd->vc.ar, s[0], s[1], 0.0f, view);
mul_m4_v3(kcd->ob->imat, view);
@@ -1509,7 +1509,6 @@ static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
static void knife_find_line_hits(KnifeTool_OpData *kcd)
{
- bglMats mats;
SmallHash faces, kfes, kfvs;
float v1[3], v2[3], v3[3], v4[3], s1[2], s2[2];
BVHTree *planetree, *tree;
@@ -1539,8 +1538,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
const bool use_hit_prev = true;
const bool use_hit_curr = (kcd->is_drag_hold == false);
- bgl_get_mats(&mats);
-
if (kcd->linehits) {
MEM_freeN(kcd->linehits);
kcd->linehits = NULL;
@@ -1669,7 +1666,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
knife_project_v2(kcd, v->cageco, s);
d = dist_squared_to_line_segment_v2(s, s1, s2);
if ((d <= vert_tol_sq) &&
- (point_is_visible(kcd, v->cageco, s, &mats, bm_elem_from_knife_vert(v, &kfe_hit))))
+ (point_is_visible(kcd, v->cageco, s, bm_elem_from_knife_vert(v, &kfe_hit))))
{
memset(&hit, 0, sizeof(hit));
hit.v = v;
@@ -1732,7 +1729,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
* Need to find 3d intersection of ray through sint */
knife_input_ray_segment(kcd, sint, 1.0f, r1, r2);
isect_kind = isect_line_line_v3(kfe->v1->cageco, kfe->v2->cageco, r1, r2, p_cage, p_cage_tmp);
- if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, &mats, bm_elem_from_knife_edge(kfe))) {
+ if (isect_kind >= 1 && point_is_visible(kcd, p_cage, sint, bm_elem_from_knife_edge(kfe))) {
memset(&hit, 0, sizeof(hit));
if (kcd->snap_midpoints) {
/* choose intermediate point snap too */
@@ -1761,7 +1758,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
float p[3], p_cage[3];
if (use_hit_prev && knife_ray_intersect_face(kcd, s1, v1, v3, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s1, &mats, (BMElem *)f)) {
+ if (point_is_visible(kcd, p_cage, s1, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1773,7 +1770,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
}
if (use_hit_curr && knife_ray_intersect_face(kcd, s2, v2, v4, f, face_tol_sq, p, p_cage)) {
- if (point_is_visible(kcd, p_cage, s2, &mats, (BMElem *)f)) {
+ if (point_is_visible(kcd, p_cage, s2, (BMElem *)f)) {
memset(&hit, 0, sizeof(hit));
hit.f = f;
copy_v3_v3(hit.hit, p);
@@ -1806,13 +1803,9 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd)
static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], const float ofs,
float r_origin[3], float r_origin_ofs[3])
{
- bglMats mats;
-
- bgl_get_mats(&mats);
-
/* unproject to find view ray */
- ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f);
- ED_view3d_unproject(&mats, r_origin_ofs, mval[0], mval[1], ofs);
+ ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], 0.0f, r_origin);
+ ED_view3d_unproject(kcd->vc.ar, mval[0], mval[1], ofs, r_origin_ofs);
/* transform into object space */
invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
@@ -3014,7 +3007,6 @@ static bool edbm_mesh_knife_point_isect(LinkNode *polys, const float cent_ss[2])
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_through)
{
KnifeTool_OpData *kcd;
- bglMats mats;
view3d_operator_needs_opengl(C);
@@ -3033,10 +3025,6 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
if (use_tag) {
BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
}
-
- if (kcd->cut_through == false) {
- bgl_get_mats(&mats);
- }
}
/* execute */
@@ -3145,7 +3133,7 @@ void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag, bool cut_throug
float cent[3], cent_ss[2];
BM_face_calc_point_in_face(f, cent);
knife_project_v2(kcd, cent, cent_ss);
- if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, &mats, (BMElem *)f)) &&
+ if ((kcd->cut_through || point_is_visible(kcd, cent, cent_ss, (BMElem *)f)) &&
edbm_mesh_knife_point_isect(polys, cent_ss))
{
BM_elem_flag_enable(f, BM_ELEM_TAG);
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 6d8a220dd86..1c9c516f1dd 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -105,7 +105,7 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
if (v3d && v3d->zbuf)
glDisable(GL_DEPTH_TEST);
- gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
gpuMultMatrix3D(lcd->ob->obmat);
unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
@@ -138,7 +138,7 @@ static void ringsel_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
immUnbindProgram();
- gpuMatrixEnd();
+ gpuPopMatrix();
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c
index e05ce727e22..1a2f9fdb62b 100644
--- a/source/blender/editors/mesh/editmesh_rip.c
+++ b/source/blender/editors/mesh/editmesh_rip.c
@@ -596,7 +596,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BMVert *v_new;
BLI_assert(l_sep->v == v);
- v_new = bmesh_urmv_loop_region(bm, l_sep);
+ v_new = BM_face_loop_separate_multi_isolated(bm, l_sep);
BLI_assert(BM_vert_find_first_loop(v));
BM_vert_select_set(bm, v, false);
@@ -665,7 +665,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve
BM_vert_select_set(bm, v, false);
- bmesh_vert_separate(bm, v, &vout, &vout_len, true);
+ bmesh_kernel_vert_separate(bm, v, &vout, &vout_len, true);
if (vout_len < 2) {
MEM_freeN(vout);
diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c
index ed5bf4a92b4..bc42717b69f 100644
--- a/source/blender/editors/metaball/mball_edit.c
+++ b/source/blender/editors/metaball/mball_edit.c
@@ -592,12 +592,9 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
view3d_set_viewcontext(C, &vc);
- rect.xmin = mval[0] - 12;
- rect.xmax = mval[0] + 12;
- rect.ymin = mval[1] - 12;
- rect.ymax = mval[1] + 12;
+ BLI_rcti_init_pt_radius(&rect, mval, 12);
- hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
+ hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
/* does startelem exist? */
ml = mb->editelems->first;
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index e7223f6f1ee..4852ae0741e 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -65,6 +65,7 @@
#include "BKE_camera.h"
#include "BKE_collection.h"
#include "BKE_context.h"
+#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
@@ -114,7 +115,7 @@
#include "UI_resources.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
#include "object_intern.h"
@@ -443,6 +444,9 @@ Object *ED_object_add_type(
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, scene);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
+
return ob;
}
@@ -1366,7 +1370,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
ob->proxy = NULL;
ob->parent = NULL;
- BLI_listbase_clear(&ob->constraints);
+ BKE_constraints_free(&ob->constraints);
ob->curve_cache = NULL;
ob->transflag &= ~OB_DUPLI;
@@ -1639,8 +1643,25 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
- CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
+ ListBase selected_editable_bases = CTX_data_collection_get(C, "selected_editable_bases");
+
+ /* Ensure we get all meshes calculated with a sufficient data-mask,
+ * needed since re-evaluating single modifiers causes bugs if they depend
+ * on other objects data masks too, see: T50950. */
{
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
+ DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
+ }
+
+ uint64_t customdata_mask_prev = scene->customdata_mask;
+ scene->customdata_mask |= CD_MASK_MESH;
+ BKE_scene_update_tagged(bmain->eval_ctx, bmain, scene);
+ scene->customdata_mask = customdata_mask_prev;
+ }
+
+ for (CollectionPointerLink *link = selected_editable_bases.first; link; link = link->next) {
+ Base *base = link->ptr.data;
ob = base->object;
if (ob->flag & OB_DONE || !IS_TAGGED(ob->data)) {
@@ -1683,7 +1704,7 @@ static int convert_exec(bContext *C, wmOperator *op)
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 */
+ else if (ob->type == OB_MESH) {
ob->flag |= OB_DONE;
if (keep_original) {
@@ -1707,7 +1728,6 @@ static int convert_exec(bContext *C, wmOperator *op)
* cases this doesnt give correct results (when MDEF is used for eg)
*/
dm = mesh_get_derived_final(scene, newob, CD_MASK_MESH);
- // dm = mesh_create_derived_no_deform(ob1, NULL); /* this was called original (instead of get_derived). man o man why! (ton) */
DM_to_mesh(dm, newob->data, newob, CD_MASK_MESH, true);
@@ -1872,11 +1892,10 @@ static int convert_exec(bContext *C, wmOperator *op)
((ID *)ob->data)->tag &= ~LIB_TAG_DOIT; /* flag not to convert this datablock again */
}
}
- CTX_DATA_END;
+ BLI_freelistN(&selected_editable_bases);
if (!keep_original) {
if (mballConverted) {
- Object *ob_mball;
FOREACH_SCENE_OBJECT(scene, ob_mball)
{
if (ob->type == OB_MBALL) {
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index 11d96da5786..bd96533a516 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -589,6 +589,7 @@ static int test_bake_internal(bContext *C, ReportList *reports)
static void init_bake_internal(BakeRender *bkr, bContext *C)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
bScreen *sc = CTX_wm_screen(C);
/* get editmode results */
@@ -597,7 +598,7 @@ static void init_bake_internal(BakeRender *bkr, bContext *C)
bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; /* can be NULL */
bkr->main = CTX_data_main(C);
bkr->scene = scene;
- bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL;
+ bkr->actob = (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT_NEW : NULL;
bkr->re = RE_NewRender("_Bake View_");
if (scene->r.bake_mode == RE_BAKE_AO) {
@@ -810,6 +811,7 @@ static int bake_image_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
int result = OPERATOR_CANCELLED;
if (is_multires_bake(scene)) {
@@ -829,7 +831,7 @@ static int bake_image_exec(bContext *C, wmOperator *op)
RE_test_break_cb(bkr.re, NULL, thread_break);
G.is_break = false; /* BKE_blender_test_break uses this global */
- RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT : NULL);
+ RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE) ? OBACT_NEW : NULL);
/* baking itself is threaded, cannot use test_break in threads */
BLI_init_threads(&threads, do_bake_render, 1);
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index fd95d6129ad..968081818a2 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -352,12 +352,17 @@ static bool is_noncolor_pass(ScenePassType pass_type)
}
/* if all is good tag image and return true */
-static bool bake_object_check(Object *ob, ReportList *reports)
+static bool bake_object_check(Scene *scene, Object *ob, ReportList *reports)
{
Image *image;
void *lock;
int i;
+ if ((ob->lay & scene->lay) == 0) {
+ BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not on a scene layer", ob->id.name + 2);
+ return false;
+ }
+
if (ob->type != OB_MESH) {
BKE_reportf(reports, RPT_ERROR, "Object \"%s\" is not a mesh", ob->id.name + 2);
return false;
@@ -491,7 +496,7 @@ static bool bake_pass_filter_check(ScenePassType pass_type, const int pass_filte
}
/* before even getting in the bake function we check for some basic errors */
-static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objects,
+static bool bake_objects_check(Main *bmain, Scene *scene, Object *ob, ListBase *selected_objects,
ReportList *reports, const bool is_selected_to_active)
{
CollectionPointerLink *link;
@@ -502,7 +507,7 @@ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objec
if (is_selected_to_active) {
int tot_objects = 0;
- if (!bake_object_check(ob, reports))
+ if (!bake_object_check(scene, ob, reports))
return false;
for (link = selected_objects->first; link; link = link->next) {
@@ -530,7 +535,7 @@ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objec
}
for (link = selected_objects->first; link; link = link->next) {
- if (!bake_object_check(link->ptr.data, reports))
+ if (!bake_object_check(scene, link->ptr.data, reports))
return false;
}
}
@@ -619,7 +624,7 @@ static Mesh *bake_mesh_new_from_object(Main *bmain, Scene *scene, Object *ob)
ED_object_editmode_load(ob);
Mesh *me = BKE_mesh_new_from_object(bmain, scene, ob, 1, 2, 0, 0);
- BKE_mesh_split_faces(me);
+ BKE_mesh_split_faces(me, true);
return me;
}
@@ -1179,7 +1184,7 @@ static int bake_exec(bContext *C, wmOperator *op)
goto finally;
}
- if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
+ if (!bake_objects_check(bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) {
goto finally;
}
@@ -1237,7 +1242,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa
return;
}
- if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
+ if (!bake_objects_check(bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) {
bkr->result = OPERATOR_CANCELLED;
return;
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 2a4557f3610..abdbf3afd5a 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -231,6 +231,7 @@ void ED_object_editmode_exit(bContext *C, int flag)
/* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
/* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
const bool freedata = (flag & EM_FREEDATA) != 0;
@@ -239,8 +240,8 @@ void ED_object_editmode_exit(bContext *C, int flag)
if (ED_object_editmode_load_ex(CTX_data_main(C), obedit, freedata) == false) {
/* in rare cases (background mode) its possible active object
* is flagged for editmode, without 'obedit' being set [#35489] */
- if (UNLIKELY(scene->basact && (scene->basact->object->mode & OB_MODE_EDIT))) {
- scene->basact->object->mode &= ~OB_MODE_EDIT;
+ if (UNLIKELY(sl->basact && (sl->basact->object->mode & OB_MODE_EDIT))) {
+ sl->basact->object->mode &= ~OB_MODE_EDIT;
}
if (flag & EM_WAITCURSOR) waitcursor(0);
return;
@@ -502,11 +503,11 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
+static void copymenu_properties(SceneLayer *sl, Object *ob)
{
//XXX no longer used - to be removed - replaced by game_properties_copy_exec
bProperty *prop;
- BaseLegacy *base;
+ Base *base;
int nr, tot = 0;
char *str;
@@ -535,8 +536,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
nr = pupmenu(str);
if (nr == 1 || nr == 2) {
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if ((base != BASACT_NEW) && (TESTBASELIB_NEW(base))) {
if (nr == 1) { /* replace */
BKE_bproperty_copy_list(&base->object->prop, &ob->prop);
}
@@ -552,8 +553,8 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
prop = BLI_findlink(&ob->prop, nr - 4); /* account for first 3 menu items & menu index starting at 1*/
if (prop) {
- for (base = FIRSTBASE; base; base = base->next) {
- if ((base != BASACT) && (TESTBASELIB(v3d, base))) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if ((base != BASACT_NEW) && (TESTBASELIB_NEW(base))) {
BKE_bproperty_object_set(base->object, prop);
}
}
@@ -563,14 +564,14 @@ static void copymenu_properties(Scene *scene, View3D *v3d, Object *ob)
}
-static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob)
+static void copymenu_logicbricks(SceneLayer *sl, Object *ob)
{
//XXX no longer used - to be removed - replaced by logicbricks_copy_exec
- BaseLegacy *base;
+ Base *base;
- for (base = FIRSTBASE; base; base = base->next) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
if (base->object != ob) {
- if (TESTBASELIB(v3d, base)) {
+ if (TESTBASELIB_NEW(base)) {
/* first: free all logic */
free_sensors(&base->object->sensors);
@@ -649,28 +650,28 @@ static void copy_texture_space(Object *to, Object *ob)
}
/* UNUSED, keep in case we want to copy functionality for use elsewhere */
-static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
+static void copy_attr(Main *bmain, Scene *scene, SceneLayer *sl, short event)
{
Object *ob;
- BaseLegacy *base;
+ Base *base;
Curve *cu, *cu1;
Nurb *nu;
bool do_depgraph_update = false;
if (ID_IS_LINKED_DATABLOCK(scene)) return;
- if (!(ob = OBACT)) return;
+ if (!(ob = OBACT_NEW)) return;
if (scene->obedit) { // XXX get from context
/* obedit_copymenu(); */
return;
}
if (event == 9) {
- copymenu_properties(scene, v3d, ob);
+ copymenu_properties(sl, ob);
return;
}
else if (event == 10) {
- copymenu_logicbricks(scene, v3d, ob);
+ copymenu_logicbricks(sl, ob);
return;
}
else if (event == 24) {
@@ -679,9 +680,9 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
return;
}
- for (base = FIRSTBASE; base; base = base->next) {
- if (base != BASACT) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (base != BASACT_NEW) {
+ if (TESTBASELIB_NEW(base)) {
DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
if (event == 1) { /* loc */
@@ -900,13 +901,13 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event)
DAG_relations_tag_update(bmain);
}
-static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d)
+static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, SceneLayer *sl)
{
Object *ob;
short event;
char str[512];
- if (!(ob = OBACT)) return;
+ if (!(ob = OBACT_NEW)) return;
if (scene->obedit) { /* XXX get from context */
/* if (ob->type == OB_MESH) */
@@ -954,7 +955,7 @@ static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *
event = pupmenu(str);
if (event <= 0) return;
- copy_attr(bmain, scene, v3d, event);
+ copy_attr(bmain, scene, sl, event);
}
/* ******************* force field toggle operator ***************** */
@@ -1317,10 +1318,10 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot)
/* ********************** */
-static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
+static void UNUSED_FUNCTION(image_aspect) (Scene *scene, SceneLayer *sl)
{
/* all selected objects with an image map: scale in image aspect */
- BaseLegacy *base;
+ Base *base;
Object *ob;
Material *ma;
Tex *tex;
@@ -1330,8 +1331,8 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d)
if (scene->obedit) return; // XXX get from context
if (ID_IS_LINKED_DATABLOCK(scene)) return;
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (TESTBASELIB_NEW(base)) {
ob = base->object;
done = false;
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index f41f21f5bd4..abb0172d9ce 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -49,6 +49,7 @@
#include "BKE_action.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -447,19 +448,19 @@ static int hook_op_edit_poll(bContext *C)
static Object *add_hook_object_new(Main *bmain, Scene *scene, SceneLayer *sl, Object *obedit)
{
- BaseLegacy *base, *basedit;
+ Base *base, *basedit;
Object *ob;
ob = BKE_object_add(bmain, scene, sl, OB_EMPTY, NULL);
- basedit = BKE_scene_base_find(scene, obedit);
- base = scene->basact;
+ basedit = BKE_scene_layer_base_find(sl, obedit);
+ base = sl->basact;
base->lay = ob->lay = obedit->lay;
- BLI_assert(scene->basact->object == ob);
+ BLI_assert(sl->basact->object == ob);
/* icky, BKE_object_add sets new base as active.
* so set it back to the original edit object */
- scene->basact = basedit;
+ sl->basact = basedit;
return ob;
}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index fe0ceb15d70..854ea9709f2 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -181,6 +181,7 @@ void OBJECT_OT_skin_loose_mark_clear(struct wmOperatorType *ot);
void OBJECT_OT_skin_radii_equalize(struct wmOperatorType *ot);
void OBJECT_OT_skin_armature_create(struct wmOperatorType *ot);
void OBJECT_OT_laplaciandeform_bind(struct wmOperatorType *ot);
+void OBJECT_OT_surfacedeform_bind(struct wmOperatorType *ot);
/* object_constraint.c */
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index bca7a163e90..fb309dc979b 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -872,7 +872,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type)
static int modifier_remove_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = ED_object_active_context(C);
ModifierData *md = edit_modifier_property_get(op, ob, 0);
int mode_orig = ob->mode;
@@ -885,7 +885,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op)
/* if cloth/softbody was removed, particle mode could be cleared */
if (mode_orig & OB_MODE_PARTICLE_EDIT)
if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0)
- if (scene->basact && scene->basact->object == ob)
+ if (sl->basact && sl->basact->object == ob)
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
return OPERATOR_FINISHED;
@@ -1485,7 +1485,6 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
Object *ob = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(ob);
BMesh *bm = em->bm;
- const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
BMVert *bm_vert;
BMIter bm_iter;
GSet *visited;
@@ -1494,6 +1493,8 @@ static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op))
BKE_mesh_ensure_skin_customdata(ob->data);
+ const int cd_vert_skin_offset = CustomData_get_offset(&bm->vdata, CD_MVERT_SKIN);
+
BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) {
if (BM_elem_flag_test(bm_vert, BM_ELEM_SELECT) &&
BLI_gset_add(visited, bm_vert))
@@ -2296,3 +2297,56 @@ void OBJECT_OT_laplaciandeform_bind(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
edit_modifier_properties(ot);
}
+
+/************************ sdef bind operator *********************/
+
+static int surfacedeform_bind_poll(bContext *C)
+{
+ return edit_modifier_poll_generic(C, &RNA_SurfaceDeformModifier, 0);
+}
+
+static int surfacedeform_bind_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_active_context(C);
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform);
+
+ if (!smd)
+ return OPERATOR_CANCELLED;
+
+ if (smd->flags & MOD_SDEF_BIND) {
+ smd->flags &= ~MOD_SDEF_BIND;
+ }
+ else if (smd->target) {
+ smd->flags |= MOD_SDEF_BIND;
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+static int surfacedeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ if (edit_modifier_invoke_properties(C, op))
+ return surfacedeform_bind_exec(C, op);
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Surface Deform Bind";
+ ot->description = "Bind mesh to target in surface deform modifier";
+ ot->idname = "OBJECT_OT_surfacedeform_bind";
+
+ /* api callbacks */
+ ot->poll = surfacedeform_bind_poll;
+ ot->invoke = surfacedeform_bind_invoke;
+ ot->exec = surfacedeform_bind_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+ edit_modifier_properties(ot);
+}
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 19526db2ce8..91950872a3d 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -249,6 +249,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_data_transfer);
WM_operatortype_append(OBJECT_OT_datalayout_transfer);
+ WM_operatortype_append(OBJECT_OT_surfacedeform_bind);
}
void ED_operatormacros_object(void)
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index c79c702837a..10439d49787 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1728,7 +1728,6 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in
* button can be functional.*/
void ED_object_single_user(Main *bmain, Scene *scene, Object *ob)
{
- Object *ob_iter;
FOREACH_SCENE_OBJECT(scene, ob_iter)
{
ob_iter->flag &= ~OB_DONE;
@@ -1855,8 +1854,6 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag)
static void single_object_action_users(Scene *scene, SceneLayer *sl, const int flag)
{
- Object *ob;
-
FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
if (!ID_IS_LINKED_DATABLOCK(ob)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -1871,7 +1868,6 @@ static void single_mat_users(Main *bmain, Scene *scene, SceneLayer *sl, const in
Tex *tex;
int a, b;
- Object *ob;
FOREACH_OBJECT_FLAG(scene, sl, flag, ob)
if (!ID_IS_LINKED_DATABLOCK(ob)) {
for (a = 1; a <= ob->totcol; a++) {
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index 37232456f48..37becfca7db 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -563,7 +563,6 @@ static bool select_grouped_children(bContext *C, Object *ob, const bool recursiv
static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */
{
SceneLayer *sl = CTX_data_scene_layer(C);
- View3D *v3d = CTX_wm_view3d(C);
Base *baspar, *basact = CTX_data_active_base(C);
bool changed = false;
@@ -574,7 +573,7 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel
baspar = BKE_scene_layer_base_find(sl, basact->object->parent);
/* can be NULL if parent in other scene */
- if (baspar && BASE_SELECTABLE(v3d, baspar)) {
+ if (baspar && BASE_SELECTABLE_NEW(baspar)) {
ED_object_base_select(baspar, BA_SELECT);
ED_object_base_activate(C, baspar);
changed = true;
@@ -632,10 +631,9 @@ static bool select_grouped_group(bContext *C, Object *ob) /* Select objects in
static bool select_grouped_object_hooks(bContext *C, Object *ob)
{
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
bool changed = false;
- BaseLegacy *base;
+ Base *base;
ModifierData *md;
HookModifierData *hmd;
@@ -644,7 +642,7 @@ static bool select_grouped_object_hooks(bContext *C, Object *ob)
hmd = (HookModifierData *) md;
if (hmd->object && !(hmd->object->flag & SELECT)) {
base = BKE_scene_base_find(scene, hmd->object);
- if (base && (BASE_SELECTABLE(v3d, base))) {
+ if (base && (BASE_SELECTABLE_NEW(base))) {
ED_base_object_select(base, BA_SELECT);
changed = true;
}
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 67ef4515c18..d93275a353e 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -59,6 +59,7 @@
#include "BKE_depsgraph.h"
#include "BKE_mesh_mapping.h"
#include "BKE_editmesh.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_report.h"
#include "BKE_DerivedMesh.h"
@@ -3300,25 +3301,26 @@ void OBJECT_OT_vertex_group_mirror(wmOperatorType *ot)
static int vertex_group_copy_to_linked_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- Object *ob = ED_object_context(C);
- BaseLegacy *base;
+ Object *ob_active = ED_object_context(C);
int retval = OPERATOR_CANCELLED;
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->type == ob->type) {
- if (base->object != ob && base->object->data == ob->data) {
- BLI_freelistN(&base->object->defbase);
- BLI_duplicatelist(&base->object->defbase, &ob->defbase);
- base->object->actdef = ob->actdef;
+ FOREACH_SCENE_OBJECT(scene, ob_iter)
+ {
+ if (ob_iter->type == ob_active->type) {
+ if (ob_iter != ob_active && ob_iter->data == ob_active->data) {
+ BLI_freelistN(&ob_iter->defbase);
+ BLI_duplicatelist(&ob_iter->defbase, &ob_active->defbase);
+ ob_iter->actdef = ob_active->actdef;
- DAG_id_tag_update(&base->object->id, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, base->object);
- WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, base->object->data);
+ DAG_id_tag_update(&ob_iter->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob_iter);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob_iter->data);
retval = OPERATOR_FINISHED;
}
}
}
+ FOREACH_SCENE_OBJECT_END
return retval;
}
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index e22a145b3a6..711ee6c8861 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -73,6 +73,8 @@
#include "ED_particle.h"
#include "ED_view3d.h"
+#include "GPU_immediate.h"
+
#include "UI_resources.h"
#include "WM_api.h"
@@ -83,7 +85,7 @@
#include "physics_intern.h"
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+void PE_create_particle_edit(Scene *scene, SceneLayer *sl, Object *ob, PointCache *cache, ParticleSystem *psys);
void PTCacheUndo_clear(PTCacheEdit *edit);
void recalc_lengths(PTCacheEdit *edit);
void recalc_emitter_field(Object *ob, ParticleSystem *psys);
@@ -109,24 +111,26 @@ void update_world_cos(Object *ob, PTCacheEdit *edit);
int PE_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+ if (!scene || !sl || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
- return (PE_get_current(scene, ob) != NULL);
+ return (PE_get_current(scene, sl, ob) != NULL);
}
int PE_hair_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
PTCacheEdit *edit;
if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
return 0;
- edit= PE_get_current(scene, ob);
+ edit= PE_get_current(scene, sl, ob);
return (edit && edit->psys);
}
@@ -211,7 +215,7 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
*
* note: this function runs on poll, therefor it can runs many times a second
* keep it fast! */
-static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
+static PTCacheEdit *pe_get_current(Scene *scene, SceneLayer *sl, Object *ob, int create)
{
ParticleEditSettings *pset= PE_settings(scene);
PTCacheEdit *edit = NULL;
@@ -222,6 +226,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
return NULL;
pset->scene = scene;
+ pset->scene_layer = sl;
pset->object = ob;
BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
@@ -250,18 +255,18 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (psys->part && psys->part->type == PART_HAIR) {
if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
if (create && !psys->pointcache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(scene, sl, ob, pid->cache, NULL);
edit = pid->cache->edit;
}
else {
if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
- PE_create_particle_edit(scene, ob, NULL, psys);
+ PE_create_particle_edit(scene, sl, ob, NULL, psys);
edit = psys->edit;
}
}
else {
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
- PE_create_particle_edit(scene, ob, pid->cache, psys);
+ PE_create_particle_edit(scene, sl, ob, pid->cache, psys);
edit = pid->cache->edit;
}
@@ -272,7 +277,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(scene, sl, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -281,7 +286,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
pset->flag |= PE_FADE_TIME;
// NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
- PE_create_particle_edit(scene, ob, pid->cache, NULL);
+ PE_create_particle_edit(scene, sl, ob, pid->cache, NULL);
}
edit = pid->cache->edit;
break;
@@ -296,14 +301,14 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
return edit;
}
-PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
+PTCacheEdit *PE_get_current(Scene *scene, SceneLayer *sl, Object *ob)
{
- return pe_get_current(scene, ob, 0);
+ return pe_get_current(scene, sl, ob, 0);
}
PTCacheEdit *PE_create_current(Scene *scene, Object *ob)
{
- return pe_get_current(scene, ob, 1);
+ return pe_get_current(scene, NULL, ob, 1);
}
void PE_current_changed(Scene *scene, Object *ob)
@@ -351,9 +356,9 @@ static int pe_x_mirror(Object *ob)
typedef struct PEData {
ViewContext vc;
- bglMats mats;
Scene *scene;
+ SceneLayer *sl;
Object *ob;
DerivedMesh *dm;
PTCacheEdit *edit;
@@ -388,8 +393,9 @@ static void PE_set_data(bContext *C, PEData *data)
memset(data, 0, sizeof(*data));
data->scene= CTX_data_scene(C);
+ data->sl = CTX_data_scene_layer(C);
data->ob= CTX_data_active_object(C);
- data->edit= PE_get_current(data->scene, data->ob);
+ data->edit= PE_get_current(data->scene, data->sl, data->ob);
}
static void PE_set_view3d_data(bContext *C, PEData *data)
@@ -397,8 +403,6 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
PE_set_data(C, data);
view3d_set_viewcontext(C, &data->vc);
- /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
- view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
if (V3D_IS_ZBUF(data->vc.v3d)) {
if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
@@ -439,7 +443,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
{
View3D *v3d= data->vc.v3d;
ViewDepths *vd = data->vc.rv3d->depths;
- double ux, uy, uz;
float depth;
/* nothing to do */
@@ -455,9 +458,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
}
#endif
- gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
- (GLint *)data->mats.viewport, &ux, &uy, &uz);
-
/* check if screen_co is within bounds because brush_cut uses out of screen coords */
if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
BLI_assert(vd && vd->depths);
@@ -467,7 +467,10 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
else
return 0;
- if ((float)uz - 0.00001f > depth)
+ float win[3];
+ ED_view3d_project(data->vc.ar, co, win);
+
+ if (win[2] - 0.00001f > depth)
return 0;
else
return 1;
@@ -1152,9 +1155,9 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
BLI_kdtree_balance(edit->emitter_field);
}
-static void PE_update_selection(Scene *scene, Object *ob, int useflag)
+static void PE_update_selection(Scene *scene, SceneLayer *sl, Object *ob, int useflag)
{
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
HairKey *hkey;
POINT_P; KEY_K;
@@ -1259,12 +1262,12 @@ static void update_velocities(PTCacheEdit *edit)
}
}
-void PE_update_object(Scene *scene, Object *ob, int useflag)
+void PE_update_object(Scene *scene, SceneLayer *sl, Object *ob, int useflag)
{
/* use this to do partial particle updates, not usable when adding or
* removing, then a full redo is necessary and calling this may crash */
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
POINT_P;
if (!edit)
@@ -1399,8 +1402,9 @@ static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, in
static int pe_select_all_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
POINT_P; KEY_K;
int action = RNA_enum_get(op->ptr, "action");
@@ -1423,7 +1427,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1452,8 +1456,9 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
{
PEData data;
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
POINT_P; KEY_K;
if (!PE_start_edit(edit))
@@ -1480,7 +1485,7 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
else
for_mouse_hit_keys(&data, toggle_key_select, 1);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1521,7 +1526,7 @@ static int select_roots_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_root);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1586,7 +1591,7 @@ static int select_tips_exec(bContext *C, wmOperator *op)
data.select_action = action;
foreach_point(&data, select_tip);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1625,6 +1630,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
PEData data;
int type;
Scene *scene;
+ SceneLayer *sl;
Object *ob;
/* used by LOOP_VISIBLE_POINTS, LOOP_VISIBLE_KEYS and LOOP_KEYS */
@@ -1644,8 +1650,9 @@ static int select_random_exec(bContext *C, wmOperator *op)
PE_set_data(C, &data);
data.select_action = SEL_SELECT;
scene = CTX_data_scene(C);
+ sl = CTX_data_scene_layer(C);
ob = CTX_data_active_object(C);
- edit = PE_get_current(scene, ob);
+ edit = PE_get_current(scene, sl, ob);
rng = BLI_rng_new_srandom(seed);
@@ -1670,7 +1677,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
BLI_rng_free(rng);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1714,7 +1721,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
data.select= !RNA_boolean_get(op->ptr, "deselect");
for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -1762,8 +1769,9 @@ void PE_deselect_all_visible(PTCacheEdit *edit)
int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1778,7 +1786,7 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1789,8 +1797,9 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
PEData data;
if (!PE_start_edit(edit))
@@ -1803,7 +1812,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
for_mouse_hit_keys(&data, select_key, 0);
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1814,10 +1823,11 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
ARegion *ar= CTX_wm_region(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
POINT_P; KEY_K;
@@ -1891,7 +1901,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1903,7 +1913,8 @@ static int hide_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
POINT_P; KEY_K;
if (RNA_enum_get(op->ptr, "unselected")) {
@@ -1925,7 +1936,7 @@ static int hide_exec(bContext *C, wmOperator *op)
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -1955,7 +1966,8 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob= CTX_data_active_object(C);
Scene *scene= CTX_data_scene(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
POINT_P; KEY_K;
LOOP_POINTS {
@@ -1968,7 +1980,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- PE_update_selection(scene, ob, 1);
+ PE_update_selection(scene, sl, ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
return OPERATOR_FINISHED;
@@ -2027,7 +2039,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_less_keys);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2089,7 +2101,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
PE_set_data(C, &data);
foreach_point(&data, select_more_keys);
- PE_update_selection(data.scene, data.ob, 1);
+ PE_update_selection(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
return OPERATOR_FINISHED;
@@ -2186,7 +2198,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
foreach_selected_point(&data, rekey_particle);
recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
+ PE_update_object(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2211,9 +2223,9 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
}
-static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
+static void rekey_particle_to_time(Scene *scene, SceneLayer *sl, Object *ob, int pa_index, float path_time)
{
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ParticleSystem *psys;
ParticleSimulationData sim= {0};
ParticleData *pa;
@@ -2517,7 +2529,7 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
foreach_point(&data, subdivide_particle);
recalc_lengths(data.edit);
- PE_update_object(data.scene, data.ob, 1);
+ PE_update_object(data.scene, data.sl, data.ob, 1);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
return OPERATOR_FINISHED;
@@ -2543,8 +2555,9 @@ void PARTICLE_OT_subdivide(wmOperatorType *ot)
static int remove_doubles_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd;
KDTree *tree;
@@ -2635,9 +2648,10 @@ void PARTICLE_OT_remove_doubles(wmOperatorType *ot)
static int weight_set_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ParticleEditSettings *pset= PE_settings(scene);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ParticleSystem *psys = edit->psys;
POINT_P;
KEY_K;
@@ -2690,24 +2704,27 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
ParticleEditSettings *pset= PE_settings(scene);
ParticleBrushData *brush;
- if (pset->brushtype < 0)
+ if (pset->brushtype < 0) {
return;
+ }
- brush= &pset->brush[pset->brushtype];
+ brush = &pset->brush[pset->brushtype];
if (brush) {
- glPushMatrix();
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- glTranslatef((float)x, (float)y, 0.0f);
+ immUniformColor4ub(255, 255, 255, 128);
- glColor4ub(255, 255, 255, 128);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40);
+
+ imm_draw_lined_circle(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
-
- glPopMatrix();
+
+ immUnbindProgram();
}
}
@@ -2791,11 +2808,11 @@ void PARTICLE_OT_delete(wmOperatorType *ot)
/*************************** mirror operator **************************/
-static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
+static void PE_mirror_x(Scene *scene, SceneLayer *sl, Object *ob, int tagged)
{
Mesh *me= (Mesh *)(ob->data);
ParticleSystemModifierData *psmd;
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ParticleSystem *psys = edit->psys;
ParticleData *pa, *newpa, *new_pars;
PTCacheEditPoint *newpoint, *new_points;
@@ -2942,10 +2959,11 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
- PE_mirror_x(scene, ob, 0);
+ PE_mirror_x(scene, sl, ob, 0);
update_world_cos(ob, edit);
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
@@ -3082,7 +3100,7 @@ static void brush_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->scene, data->sl, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -3711,6 +3729,7 @@ static int brush_add(PEData *data, short number)
typedef struct BrushEdit {
Scene *scene;
+ SceneLayer *sl;
Object *ob;
PTCacheEdit *edit;
@@ -3725,9 +3744,10 @@ typedef struct BrushEdit {
static int brush_edit_init(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= CTX_data_active_object(C);
ParticleEditSettings *pset= PE_settings(scene);
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ARegion *ar= CTX_wm_region(C);
BrushEdit *bedit;
float min[3], max[3];
@@ -3737,7 +3757,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
/* set the 'distance factor' for grabbing (used in comb etc) */
INIT_MINMAX(min, max);
- PE_minmax(scene, min, max);
+ PE_minmax(scene, sl, min, max);
mid_v3_v3v3(min, min, max);
bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
@@ -3745,6 +3765,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
op->customdata= bedit;
bedit->scene= scene;
+ bedit->sl = sl;
bedit->ob= ob;
bedit->edit= edit;
@@ -3760,6 +3781,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
{
BrushEdit *bedit= op->customdata;
Scene *scene= bedit->scene;
+ SceneLayer *sl = bedit->sl;
Object *ob= bedit->ob;
PTCacheEdit *edit= bedit->edit;
ParticleEditSettings *pset= PE_settings(scene);
@@ -3950,14 +3972,14 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) {
if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
- PE_mirror_x(scene, ob, 1);
+ PE_mirror_x(scene, sl, ob, 1);
update_world_cos(ob, edit);
psys_free_path_cache(NULL, edit);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else
- PE_update_object(scene, ob, 1);
+ PE_update_object(scene, sl, ob, 1);
}
if (edit->psys) {
@@ -4170,7 +4192,7 @@ static void shape_cut(PEData *data, int pa_index)
edit->points[pa_index].flag |= PEP_TAG;
}
else {
- rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+ rekey_particle_to_time(data->scene, data->sl, ob, pa_index, cut_time);
edit->points[pa_index].flag |= PEP_EDIT_RECALC;
}
}
@@ -4179,9 +4201,10 @@ static void shape_cut(PEData *data, int pa_index)
static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(scene);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
Object *shapeob = pset->shape_object;
int selected = count_selected_keys(scene, edit);
int lock_root = pset->flag & PE_LOCK_FIRST;
@@ -4217,7 +4240,7 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
else
- PE_update_object(scene, ob, 1);
+ PE_update_object(scene, sl, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
@@ -4389,9 +4412,9 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
}
}
-void PE_undo_push(Scene *scene, const char *str)
+void PE_undo_push(Scene *scene, SceneLayer *sl, const char *str)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, sl, OBACT_NEW);
PTCacheUndo *undo;
int nr;
@@ -4431,9 +4454,9 @@ void PE_undo_push(Scene *scene, const char *str)
make_PTCacheUndo(edit, edit->curundo);
}
-void PE_undo_step(Scene *scene, int step)
+void PE_undo_step(Scene *scene, SceneLayer *sl, int step)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, sl, OBACT_NEW);
if (!edit) return;
@@ -4464,12 +4487,12 @@ void PE_undo_step(Scene *scene, int step)
}
}
- DAG_id_tag_update(&OBACT->id, OB_RECALC_DATA);
+ DAG_id_tag_update(&OBACT_NEW->id, OB_RECALC_DATA);
}
-bool PE_undo_is_valid(Scene *scene)
+bool PE_undo_is_valid(Scene *scene, SceneLayer *sl)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, sl, OBACT_NEW);
if (edit) {
return (edit->undo.last != edit->undo.first);
@@ -4492,19 +4515,19 @@ void PTCacheUndo_clear(PTCacheEdit *edit)
edit->curundo= NULL;
}
-void PE_undo(Scene *scene)
+void PE_undo(Scene *scene, SceneLayer *sl)
{
- PE_undo_step(scene, 1);
+ PE_undo_step(scene, sl, 1);
}
-void PE_redo(Scene *scene)
+void PE_redo(Scene *scene, SceneLayer *sl)
{
- PE_undo_step(scene, -1);
+ PE_undo_step(scene, sl, -1);
}
-void PE_undo_number(Scene *scene, int nr)
+void PE_undo_number(Scene *scene, SceneLayer *sl, int nr)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, sl, OBACT_NEW);
PTCacheUndo *undo;
int a=0;
@@ -4512,15 +4535,15 @@ void PE_undo_number(Scene *scene, int nr)
if (a==nr) break;
}
edit->curundo= undo;
- PE_undo_step(scene, 0);
+ PE_undo_step(scene, sl, 0);
}
/* get name of undo item, return null if no item with this index */
/* if active pointer, set it to 1 if true */
-const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
+const char *PE_undo_get_name(Scene *scene, SceneLayer *sl, int nr, bool *r_active)
{
- PTCacheEdit *edit= PE_get_current(scene, OBACT);
+ PTCacheEdit *edit= PE_get_current(scene, sl, OBACT_NEW);
PTCacheUndo *undo;
if (r_active) *r_active = false;
@@ -4539,10 +4562,10 @@ const char *PE_undo_get_name(Scene *scene, int nr, bool *r_active)
/************************ utilities ******************************/
-int PE_minmax(Scene *scene, float min[3], float max[3])
+int PE_minmax(Scene *scene, SceneLayer *sl, float min[3], float max[3])
{
- Object *ob= OBACT;
- PTCacheEdit *edit= PE_get_current(scene, ob);
+ Object *ob= OBACT_NEW;
+ PTCacheEdit *edit= PE_get_current(scene, sl, ob);
ParticleSystem *psys;
ParticleSystemModifierData *psmd = NULL;
POINT_P; KEY_K;
@@ -4579,7 +4602,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
/************************ particle edit toggle operator ************************/
/* initialize needed data for bake edit */
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+void PE_create_particle_edit(Scene *scene, SceneLayer *sl, Object *ob, PointCache *cache, ParticleSystem *psys)
{
PTCacheEdit *edit;
ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
@@ -4680,10 +4703,10 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
recalc_lengths(edit);
if (psys && !cache)
recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, 1);
+ PE_update_object(scene, sl, ob, 1);
PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
+ PE_undo_push(scene, sl, "Original");
}
}
@@ -4887,14 +4910,15 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = CTX_data_active_object(C);
Scene *scene = CTX_data_scene(C);
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
float average_length = calculate_average_length(edit);
if (average_length == 0.0f) {
return OPERATOR_CANCELLED;
}
scale_points_to_length(edit, average_length);
- PE_update_object(scene, ob, 1);
+ PE_update_object(scene, sl, ob, 1);
if (edit->psys) {
WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
}
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 4a4474868a2..782e0253267 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -69,7 +69,7 @@
#include "physics_intern.h"
-extern void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
+extern void PE_create_particle_edit(Scene *scene, SceneLayer *sl, Object *ob, PointCache *cache, ParticleSystem *psys);
extern void PTCacheUndo_clear(PTCacheEdit *edit);
extern void recalc_lengths(PTCacheEdit *edit);
extern void recalc_emitter_field(Object *ob, ParticleSystem *psys);
@@ -133,6 +133,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob = ED_object_context(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
int mode_orig;
if (!scene || !ob)
@@ -146,7 +147,7 @@ static int particle_system_remove_exec(bContext *C, wmOperator *UNUSED(op))
*/
if (mode_orig & OB_MODE_PARTICLE_EDIT) {
if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
- if (scene->basact && scene->basact->object == ob) {
+ if (sl->basact && sl->basact->object == ob) {
WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
}
}
@@ -565,7 +566,7 @@ void PARTICLE_OT_dupliob_move_down(wmOperatorType *ot)
/************************ connect/disconnect hair operators *********************/
-static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static void disconnect_hair(Scene *scene, SceneLayer *sl, Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
ParticleEditSettings *pset= PE_settings(scene);
@@ -611,12 +612,13 @@ static void disconnect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
if (ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_PUFF))
pset->brushtype = PE_BRUSH_NONE;
- PE_update_object(scene, ob, 0);
+ PE_update_object(scene, sl, ob, 0);
}
static int disconnect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -626,12 +628,12 @@ static int disconnect_hair_exec(bContext *C, wmOperator *op)
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- disconnect_hair(scene, ob, psys);
+ disconnect_hair(scene, sl, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- disconnect_hair(scene, ob, psys);
+ disconnect_hair(scene, sl, ob, psys);
}
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
@@ -657,7 +659,7 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot)
/* from/to_world_space : whether from/to particles are in world or hair space
* from/to_mat : additional transform for from/to particles (e.g. for using object space copying)
*/
-static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
+static bool remap_hair_emitter(Scene *scene, SceneLayer *sl, Object *ob, ParticleSystem *psys,
Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit,
float from_mat[4][4], float to_mat[4][4], bool from_global, bool to_global)
{
@@ -843,19 +845,19 @@ static bool remap_hair_emitter(Scene *scene, Object *ob, ParticleSystem *psys,
psys_free_path_cache(target_psys, target_edit);
- PE_update_object(scene, target_ob, 0);
+ PE_update_object(scene, sl, target_ob, 0);
return true;
}
-static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
+static bool connect_hair(Scene *scene, SceneLayer *sl, Object *ob, ParticleSystem *psys)
{
bool ok;
if (!psys)
return false;
- ok = remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
+ ok = remap_hair_emitter(scene, sl, ob, psys, ob, psys, psys->edit, ob->obmat, ob->obmat, psys->flag & PSYS_GLOBAL_HAIR, false);
psys->flag &= ~PSYS_GLOBAL_HAIR;
return ok;
@@ -864,6 +866,7 @@ static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys)
static int connect_hair_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob= ED_object_context(C);
ParticleSystem *psys= NULL;
const bool all = RNA_boolean_get(op->ptr, "all");
@@ -874,12 +877,12 @@ static int connect_hair_exec(bContext *C, wmOperator *op)
if (all) {
for (psys=ob->particlesystem.first; psys; psys=psys->next) {
- any_connected |= connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(scene, sl, ob, psys);
}
}
else {
psys = psys_get_current(ob);
- any_connected |= connect_hair(scene, ob, psys);
+ any_connected |= connect_hair(scene, sl, ob, psys);
}
if (!any_connected) {
@@ -915,7 +918,7 @@ typedef enum eCopyParticlesSpace {
PAR_COPY_SPACE_WORLD = 1,
} eCopyParticlesSpace;
-static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
+static void copy_particle_edit(Scene *scene, SceneLayer *sl, Object *ob, ParticleSystem *psys, ParticleSystem *psys_from)
{
PTCacheEdit *edit_from = psys_from->edit, *edit;
ParticleData *pa;
@@ -965,10 +968,10 @@ static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, P
recalc_lengths(edit);
recalc_emitter_field(ob, psys);
- PE_update_object(scene, ob, true);
+ PE_update_object(scene, sl, ob, true);
PTCacheUndo_clear(edit);
- PE_undo_push(scene, "Original");
+ PE_undo_push(scene, sl, "Original");
}
static void remove_particle_systems_from_object(Object *ob_to)
@@ -998,6 +1001,7 @@ static void remove_particle_systems_from_object(Object *ob_to)
/* single_psys_from is optional, if NULL all psys of ob_from are copied */
static bool copy_particle_systems_to_object(Main *bmain,
Scene *scene,
+ SceneLayer *sl,
Object *ob_from,
ParticleSystem *single_psys_from,
Object *ob_to,
@@ -1078,7 +1082,7 @@ static bool copy_particle_systems_to_object(Main *bmain,
DM_ensure_tessface(psmd->dm_final);
if (psys_from->edit)
- copy_particle_edit(scene, ob_to, psys, psys_from);
+ copy_particle_edit(scene, sl, ob_to, psys, psys_from);
if (duplicate_settings) {
id_us_min(&psys->part->id);
@@ -1112,7 +1116,7 @@ static bool copy_particle_systems_to_object(Main *bmain,
break;
}
if (ob_from != ob_to) {
- remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
+ remap_hair_emitter(scene, sl, ob_from, psys_from, ob_to, psys, psys->edit, from_mat, to_mat, psys_from->flag & PSYS_GLOBAL_HAIR, psys->flag & PSYS_GLOBAL_HAIR);
}
/* tag for recalc */
@@ -1147,6 +1151,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
const bool use_active = RNA_boolean_get(op->ptr, "use_active");
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob_from = ED_object_active_context(C);
ParticleSystem *psys_from = use_active ? CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data : NULL;
@@ -1161,7 +1166,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
remove_particle_systems_from_object(ob_to);
changed = true;
}
- if (copy_particle_systems_to_object(bmain, scene, ob_from, psys_from, ob_to, space, false))
+ if (copy_particle_systems_to_object(bmain, scene, sl, ob_from, psys_from, ob_to, space, false))
changed = true;
else
fail++;
@@ -1222,7 +1227,7 @@ static int duplicate_particle_systems_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
Object *ob = ED_object_active_context(C);
ParticleSystem *psys = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem).data;
- copy_particle_systems_to_object(CTX_data_main(C), scene, ob, psys, ob,
+ copy_particle_systems_to_object(CTX_data_main(C), scene, CTX_data_scene_layer(C), ob, psys, ob,
PAR_COPY_SPACE_OBJECT, duplicate_settings);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index 4b19e235d9c..5a2bb1e74c7 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -42,6 +42,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -253,22 +254,23 @@ static void ptcache_bake_cancel(bContext *C, wmOperator *op)
static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
{
- Scene *scene= CTX_data_scene(C);
- BaseLegacy *base;
+ Scene *scene = CTX_data_scene(C);
PTCacheID *pid;
ListBase pidlist;
- for (base=scene->base.first; base; base= base->next) {
- BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
- for (pid=pidlist.first; pid; pid=pid->next) {
+ for (pid = pidlist.first; pid; pid = pid->next) {
ptcache_free_bake(pid->cache);
}
BLI_freelistN(&pidlist);
- WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object);
+ WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob);
}
+ FOREACH_SCENE_OBJECT_END
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c
index b7be31602d9..fb75e27131b 100644
--- a/source/blender/editors/physics/rigidbody_constraint.c
+++ b/source/blender/editors/physics/rigidbody_constraint.c
@@ -117,8 +117,9 @@ static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
- Object *ob = (scene) ? OBACT : NULL;
+ Object *ob = OBACT_NEW;
int type = RNA_enum_get(op->ptr, "type");
bool changed;
@@ -166,11 +167,8 @@ 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;
-
- /* sanity checks */
- if (scene == NULL)
- return OPERATOR_CANCELLED;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
/* apply to active object */
if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c
index 07f4679a32a..a28e9e4b4a3 100644
--- a/source/blender/editors/render/render_internal.c
+++ b/source/blender/editors/render/render_internal.c
@@ -81,6 +81,7 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
+#include "GPU_shader.h"
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -780,18 +781,18 @@ static void screen_render_cancel(bContext *C, wmOperator *op)
WM_jobs_kill_type(wm, scene, WM_JOB_TYPE_RENDER);
}
-static void clean_viewport_memory(Main *bmain, Scene *scene, int renderlay)
+static void clean_viewport_memory(Main *bmain, Scene *scene)
{
Object *object;
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
for (object = bmain->object.first; object; object = object->id.next) {
object->id.tag |= LIB_TAG_DOIT;
}
for (SETLOOPER(scene, sce_iter, base)) {
- if ((base->lay & renderlay) == 0) {
+ if ((base->flag & BASE_VISIBLED) == 0) {
continue;
}
if (RE_allow_render_generic_object(base->object)) {
@@ -927,8 +928,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
/* Lock the user interface depending on render settings. */
if (scene->r.use_lock_interface) {
- int renderlay = rj->lay_override ? rj->lay_override : scene->lay;
-
WM_set_locked_interface(CTX_wm_manager(C), true);
/* Set flag interface need to be unlocked.
@@ -942,7 +941,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
rj->interface_locked = true;
/* Clean memory used by viewport? */
- clean_viewport_memory(rj->main, scene, renderlay);
+ clean_viewport_memory(rj->main, scene);
}
/* setup job */
@@ -1539,11 +1538,10 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
if (force_fallback == false) {
if (IMB_colormanagement_setup_glsl_draw(&scene->view_settings, &scene->display_settings, dither, true)) {
glEnable(GL_BLEND);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glPixelZoom(scale_x, scale_y);
- glaDrawPixelsTex(xof, yof, rres.rectx, rres.recty,
- GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf);
- glPixelZoom(1.0f, 1.0f);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(xof, yof, rres.rectx, rres.recty,
+ GL_RGBA, GL_FLOAT, GL_NEAREST, rres.rectf,
+ scale_x, scale_y, NULL);;
glDisable(GL_BLEND);
IMB_colormanagement_finish_glsl_draw();
@@ -1560,12 +1558,11 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C)
4, dither, &scene->view_settings, &scene->display_settings);
glEnable(GL_BLEND);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- glPixelZoom(scale_x, scale_y);
- glaDrawPixelsAuto(xof, yof, rres.rectx, rres.recty,
- GL_RGBA, GL_UNSIGNED_BYTE,
- GL_NEAREST, display_buffer);
- glPixelZoom(1.0f, 1.0f);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(xof, yof, rres.rectx, rres.recty,
+ GL_RGBA, GL_UNSIGNED_BYTE,
+ GL_NEAREST, display_buffer,
+ scale_x, scale_y, NULL);
glDisable(GL_BLEND);
MEM_freeN(display_buffer);
diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c
index 9097432a251..91bf0eeaa38 100644
--- a/source/blender/editors/render/render_opengl.c
+++ b/source/blender/editors/render/render_opengl.c
@@ -71,9 +71,9 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "GPU_glew.h"
#include "GPU_compositing.h"
#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
#include "render_intern.h"
@@ -92,6 +92,7 @@ typedef struct OGLRender {
Main *bmain;
Render *re;
Scene *scene;
+ SceneLayer *scene_layer;
View3D *v3d;
RegionView3D *rv3d;
@@ -277,6 +278,7 @@ static void screen_opengl_views_setup(OGLRender *oglrender)
static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
{
Scene *scene = oglrender->scene;
+ SceneLayer *sl = oglrender->scene_layer;
ARegion *ar = oglrender->ar;
View3D *v3d = oglrender->v3d;
RegionView3D *rv3d = oglrender->rv3d;
@@ -315,7 +317,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
IMB_freeImBuf(out);
}
- else if (gpd){
+ else if (gpd) {
/* If there are no strips, Grease Pencil still needs a buffer to draw on */
ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect);
RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
@@ -333,7 +335,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
wmOrtho2(0, sizex, 0, sizey);
- glTranslatef(sizex / 2, sizey / 2, 0.0f);
+ gpuTranslate2f(sizex / 2, sizey / 2);
G.f |= G_RENDER_OGL;
ED_gpencil_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
@@ -358,7 +360,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
if (view_context) {
ibuf_view = ED_view3d_draw_offscreen_imbuf(
- scene, v3d, ar, sizex, sizey,
+ scene, sl, v3d, ar, sizex, sizey,
IB_rect, draw_bgpic,
alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
@@ -370,7 +372,7 @@ static void screen_opengl_render_doit(OGLRender *oglrender, RenderResult *rr)
}
else {
ibuf_view = ED_view3d_draw_offscreen_imbuf_simple(
- scene, scene->camera, oglrender->sizex, oglrender->sizey,
+ scene, sl, scene->camera, oglrender->sizex, oglrender->sizey,
IB_rect, OB_SOLID, false, true, true,
alpha_mode, oglrender->ofs_samples, oglrender->ofs_full_samples, viewname,
oglrender->fx, oglrender->ofs, err_out);
@@ -650,6 +652,7 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->sizey = sizey;
oglrender->bmain = CTX_data_main(C);
oglrender->scene = scene;
+ oglrender->scene_layer = CTX_data_scene_layer(C);
oglrender->cfrao = scene->r.cfra;
oglrender->write_still = is_write_still && !is_animation;
@@ -715,7 +718,6 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op)
oglrender->task_scheduler = task_scheduler;
oglrender->task_pool = BLI_task_pool_create_background(task_scheduler,
oglrender);
- BLI_pool_set_num_threads(oglrender->task_pool, 1);
}
else {
oglrender->task_scheduler = NULL;
@@ -747,6 +749,23 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
int i;
if (oglrender->is_animation) {
+ /* Trickery part for movie output:
+ *
+ * We MUST write frames in an exact order, so we only let background
+ * thread to work on that, and main thread is simply waits for that
+ * thread to do all the dirty work.
+ *
+ * After this loop is done work_and_wait() will have nothing to do,
+ * so we don't run into wrong order of frames written to the stream.
+ */
+ if (BKE_imtype_is_movie(scene->r.im_format.imtype)) {
+ BLI_mutex_lock(&oglrender->task_mutex);
+ while (oglrender->num_scheduled_frames > 0) {
+ BLI_condition_wait(&oglrender->task_condition,
+ &oglrender->task_mutex);
+ }
+ BLI_mutex_unlock(&oglrender->task_mutex);
+ }
BLI_task_pool_work_and_wait(oglrender->task_pool);
BLI_task_pool_free(oglrender->task_pool);
/* Depending on various things we might or might not use global scheduler. */
@@ -886,14 +905,15 @@ static void write_result_func(TaskPool * __restrict pool,
*/
ReportList reports;
BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
- /* Do actual save logic here, depending on the file format. */
+ /* Do actual save logic here, depending on the file format.
+ *
+ * NOTE: We have to construct temporary scene with proper scene->r.cfra.
+ * This is because underlying calls do not use r.cfra but use scene
+ * for that.
+ */
+ Scene tmp_scene = *scene;
+ tmp_scene.r.cfra = cfra;
if (is_movie) {
- /* We have to construct temporary scene with proper scene->r.cfra.
- * This is because underlying calls do not use r.cfra but use scene
- * for that.
- */
- Scene tmp_scene = *scene;
- tmp_scene.r.cfra = cfra;
ok = RE_WriteRenderViewsMovie(&reports,
rr,
&tmp_scene,
@@ -917,8 +937,8 @@ static void write_result_func(TaskPool * __restrict pool,
true,
NULL);
- BKE_render_result_stamp_info(scene, scene->camera, rr, false);
- ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
+ BKE_render_result_stamp_info(&tmp_scene, tmp_scene.camera, rr, false);
+ ok = RE_WriteRenderViewsImage(NULL, rr, &tmp_scene, true, name);
if (!ok) {
BKE_reportf(&reports,
RPT_ERROR,
diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c
index cb54f0efd85..3fb09123131 100644
--- a/source/blender/editors/render/render_preview.c
+++ b/source/blender/editors/render/render_preview.c
@@ -69,6 +69,7 @@
#include "BKE_image.h"
#include "BKE_icons.h"
#include "BKE_lamp.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_main.h"
@@ -85,6 +86,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_shader.h"
#include "RE_pipeline.h"
#include "RE_engine.h"
@@ -197,7 +199,7 @@ static Main *load_main_from_memory(const void *blend, int blend_size)
BlendFileData *bfd;
G.fileflags |= G_FILE_NO_UI;
- bfd = BLO_read_from_memory(blend, blend_size, NULL);
+ bfd = BLO_read_from_memory(blend, blend_size, NULL, BLO_READ_SKIP_NONE);
if (bfd) {
bmain = bfd->main;
@@ -358,29 +360,33 @@ static Scene *preview_prepare_scene(Main *bmain, Scene *scene, ID *id, int id_ty
/* this only works in a specific case where the preview.blend contains
* an object starting with 'c' which has a material linked to it (not the obdata)
* and that material has a fake shadow texture in the active texture slot */
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->id.name[2] == 'c') {
- Material *shadmat = give_current_material(base->object, base->object->actcol);
+ FOREACH_SCENE_OBJECT(sce, ob)
+ {
+ if (ob->id.name[2] == 'c') {
+ Material *shadmat = give_current_material(ob, ob->actcol);
if (shadmat) {
if (mat->mode2 & MA_CASTSHADOW) shadmat->septex = 0;
else shadmat->septex |= 1;
}
}
}
+ FOREACH_SCENE_OBJECT_END
/* turn off bounce lights for volume,
* doesn't make much visual difference and slows it down too */
- for (base = sce->base.first; base; base = base->next) {
- if (base->object->type == OB_LAMP) {
+ FOREACH_SCENE_OBJECT(sce, ob)
+ {
+ if (ob->type == OB_LAMP) {
/* if doesn't match 'Lamp.002' --> main key light */
- if (!STREQ(base->object->id.name + 2, "Lamp.002")) {
+ if (!STREQ(ob->id.name + 2, "Lamp.002")) {
if (mat->material_type == MA_TYPE_VOLUME)
- base->object->restrictflag |= OB_RESTRICT_RENDER;
+ ob->restrictflag |= OB_RESTRICT_RENDER;
else
- base->object->restrictflag &= ~OB_RESTRICT_RENDER;
+ ob->restrictflag &= ~OB_RESTRICT_RENDER;
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
else {
/* use current scene world to light sphere */
@@ -594,7 +600,9 @@ static bool ed_preview_draw_rect(ScrArea *sa, int split, int first, rcti *rect,
if (re)
RE_AcquiredResultGet32(re, &rres, (unsigned int *)rect_byte, 0);
- glaDrawPixelsSafe(fx, fy, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_UNSIGNED_BYTE, rect_byte);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(fx, fy, rres.rectx, rres.recty, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect_byte,
+ 1.0f, 1.0f, NULL);
MEM_freeN(rect_byte);
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 986e9623fef..b58bd43a35e 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -631,6 +631,7 @@ static int render_layer_add_exec(bContext *C, wmOperator *UNUSED(op))
scene->active_layer = BLI_listbase_count(&scene->render_layers) - 1;
DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
return OPERATOR_FINISHED;
@@ -653,13 +654,14 @@ void SCENE_OT_render_layer_add(wmOperatorType *ot)
static int render_layer_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
- SceneLayer *sl = BKE_scene_layer_active(scene);
+ SceneLayer *sl = BKE_scene_layer_context_active(scene);
if (!BKE_scene_layer_remove(CTX_data_main(C), scene, sl)) {
return OPERATOR_CANCELLED;
}
DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, scene);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c
index f11a8177bf8..46c3417e8c2 100644
--- a/source/blender/editors/render/render_update.c
+++ b/source/blender/editors/render/render_update.c
@@ -48,12 +48,14 @@
#include "BKE_context.h"
#include "BKE_DerivedMesh.h"
#include "BKE_icons.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_buffers.h"
@@ -374,6 +376,7 @@ static void texture_changed(Main *bmain, Tex *tex)
Lamp *la;
World *wo;
Scene *scene;
+ SceneLayer *sl;
Object *ob;
bNode *node;
bool texture_draw = false;
@@ -382,8 +385,11 @@ static void texture_changed(Main *bmain, Tex *tex)
BKE_icon_changed(BKE_icon_id_ensure(&tex->id));
/* paint overlays */
- for (scene = bmain->scene.first; scene; scene = scene->id.next)
- BKE_paint_invalidate_overlay_tex(scene, tex);
+ for (scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (sl = scene->render_layers.first; sl; sl = sl->next) {
+ BKE_paint_invalidate_overlay_tex(scene, sl, tex);
+ }
+ }
/* find materials */
for (ma = bmain->mat.first; ma; ma = ma->id.next) {
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index dbecbb974f7..0d3a060b8ee 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -58,9 +58,9 @@
#include "ED_space_api.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_draw.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BLF_api.h"
@@ -74,7 +74,7 @@
#include "screen_intern.h"
-extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */
+extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); /* xxx temp */
/* general area and region code */
@@ -92,9 +92,9 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GL_LINE_STRIP, 5);
@@ -123,7 +123,7 @@ static void region_draw_emboss(const ARegion *ar, const rcti *scirct)
void ED_region_pixelspace(ARegion *ar)
{
wmOrtho2_region_pixelspace(ar);
- glLoadIdentity();
+ gpuLoadIdentity();
}
/* only exported for WM */
@@ -222,9 +222,9 @@ static void area_draw_azone_fullscreen(short x1, short y1, short x2, short y2, f
BLI_rcti_init(&click_rect, x, x + icon_size, y, y + icon_size);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
immAttrib4ub(color, 255, 0, 0, alpha_debug);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -255,9 +255,9 @@ static void area_draw_azone(short x1, short y1, short x2, short y2)
glEnable(GL_LINE_SMOOTH);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
- unsigned col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
immBegin(GL_LINES, 12);
@@ -297,12 +297,12 @@ static void region_draw_azone_icon(AZone *az)
float midx = az->x1 + (az->x2 - az->x1) * 0.5f;
float midy = az->y1 + (az->y2 - az->y1) * 0.5f;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
/* outlined circle */
GPU_enable_program_point_size(); /* TODO: make a fixed-size shader to avoid this */
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform4f("color", 1.0f, 1.0f, 1.0f, 0.8f);
immUniform4f("outlineColor", 0.2f, 0.2f, 0.2f, 0.9f);
immUniform1f("outlineWidth", 1.0f);
@@ -330,8 +330,8 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2)
float width = 0.1f * U.widget_unit;
float pad = 0.2f * U.widget_unit;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
glEnable(GL_BLEND);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -414,24 +414,24 @@ static void region_draw_azone_tria(AZone *az)
{
glEnable(GL_BLEND);
//UI_GetThemeColor3fv(TH_HEADER, col);
- glColor4f(0.0f, 0.0f, 0.0f, 0.35f);
+ float color[4] = {0.0f, 0.0f, 0.0f, 0.35f};
/* add code to draw region hidden as 'too small' */
switch (az->edge) {
case AE_TOP_TO_BOTTOMRIGHT:
- ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2);
+ ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x2, (float)az->y1, (float)(az->x1 + az->x2) / 2, (float)az->y2, color);
break;
case AE_BOTTOM_TO_TOPLEFT:
- ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1);
+ ui_draw_anti_tria((float)az->x1, (float)az->y2, (float)az->x2, (float)az->y2, (float)(az->x1 + az->x2) / 2, (float)az->y1, color);
break;
case AE_LEFT_TO_TOPRIGHT:
- ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2);
+ ui_draw_anti_tria((float)az->x2, (float)az->y1, (float)az->x2, (float)az->y2, (float)az->x1, (float)(az->y1 + az->y2) / 2, color);
break;
case AE_RIGHT_TO_TOPLEFT:
- ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2);
+ ui_draw_anti_tria((float)az->x1, (float)az->y1, (float)az->x1, (float)az->y2, (float)az->x2, (float)(az->y1 + az->y2) / 2, color);
break;
}
@@ -455,8 +455,8 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPushMatrix();
- glTranslatef(-ar->winrct.xmin, -ar->winrct.ymin, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(-ar->winrct.xmin, -ar->winrct.ymin);
for (az = sa->actionzones.first; az; az = az->next) {
/* test if action zone is over this region */
@@ -493,7 +493,7 @@ static void region_draw_azones(ScrArea *sa, ARegion *ar)
}
}
- glPopMatrix();
+ gpuPopMatrix();
glDisable(GL_BLEND);
}
@@ -570,8 +570,8 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
/* for debugging unneeded area redraws and partial redraw */
#if 0
glEnable(GL_BLEND);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(drand48(), drand48(), drand48(), 0.1f);
immRectf(pos, ar->drawrct.xmin - ar->winrct.xmin, ar->drawrct.ymin - ar->winrct.ymin,
@@ -1795,7 +1795,7 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco)
RNA_pointer_create(&(scr->id), &RNA_Area, sa, &areaptr);
- uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.5 * U.widget_unit, U.widget_unit,
+ uiDefButR(block, UI_BTYPE_MENU, 0, "", xco, yco, 1.6 * U.widget_unit, U.widget_unit,
&areaptr, "type", 0, 0.0f, 0.0f, 0.0f, 0.0f, "");
return xco + 1.7 * U.widget_unit;
@@ -2014,8 +2014,8 @@ void ED_region_panels(const bContext *C, ARegion *ar, const char *context, int c
/* view should be in pixelspace */
UI_view2d_view_restore(C);
glEnable(GL_BLEND);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor((ar->type->regionid == RGN_TYPE_PREVIEW) ? TH_PREVIEW_BACK : TH_BACK);
immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct) + 1);
@@ -2148,8 +2148,8 @@ void ED_region_info_draw(ARegion *ar, const char *text, float fill_color[4], con
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(fill_color);
immRecti(pos, rect.xmin, rect.ymin, rect.xmax + 1, rect.ymax + 1);
@@ -2338,11 +2338,11 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
return;
/* find window pixel coordinates of origin */
- glPushMatrix();
+ gpuPushMatrix();
/* offset and zoom using ogl */
- glTranslatef(x, y, 0.0f);
- glScalef(zoomx, zoomy, 1.0f);
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
BLF_size(blf_mono_font, style->widgetlabel.points * 1.5f * U.pixelsize, U.dpi);
@@ -2355,8 +2355,8 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
/* set up rect */
BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymax, frame->ymax + box_y);
/* draw top box */
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_METADATA_BG);
immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2380,8 +2380,8 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
/* set up box rect */
BLI_rctf_init(&rect, frame->xmin, frame->xmax, frame->ymin - box_y, frame->ymin);
/* draw top box */
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_METADATA_BG);
immRectf(pos, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
@@ -2396,7 +2396,7 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
BLF_disable(blf_mono_font, BLF_CLIPPING);
}
- glPopMatrix();
+ gpuPopMatrix();
}
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
@@ -2409,8 +2409,8 @@ void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColorShade(TH_BACK, 20);
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index 14d877a8d69..a9e1738a1a3 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -50,79 +50,10 @@
#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "UI_interface.h"
-/* DEPRECATED: use imm_draw_line instead */
-void fdrawline(float x1, float y1, float x2, float y2)
-{
- glBegin(GL_LINES);
- glVertex2f(x1, y1);
- glVertex2f(x2, y2);
- glEnd();
-}
-
-void fdrawbox(float x1, float y1, float x2, float y2)
-{
- /* DEPRECATED: use imm_draw_line_box instead */
- glBegin(GL_LINE_LOOP);
-
- glVertex2f(x1, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y2);
- glVertex2f(x2, y1);
-
- glEnd();
-}
-
-void fdrawbox_filled(float x1, float y1, float x2, float y2)
-{
- glBegin(GL_POLYGON);
-
- glVertex2f(x1, y1);
- glVertex2f(x1, y2);
- glVertex2f(x2, y2);
- glVertex2f(x2, y1);
-
- glEnd();
-}
-
-void fdrawcheckerboard(float x1, float y1, float x2, float y2) /* DEPRECATED */
-{
- unsigned char col1[4] = {40, 40, 40}, col2[4] = {50, 50, 50};
-
- glColor3ubv(col1);
- glRectf(x1, y1, x2, y2);
- glColor3ubv(col2);
-
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_CHECKER_8PX);
- glRectf(x1, y1, x2, y2);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-}
-
-void sdrawline(int x1, int y1, int x2, int y2) /* DEPRECATED */
-{
- glBegin(GL_LINES);
- glVertex2i(x1, y1);
- glVertex2i(x2, y2);
- glEnd();
-}
-
-void sdrawbox(int x1, int y1, int x2, int y2)
-{
- /* DEPRECATED: use imm_draw_line_box instead */
- glBegin(GL_LINE_LOOP);
-
- glVertex2i(x1, y1);
- glVertex2i(x1, y2);
- glVertex2i(x2, y2);
- glVertex2i(x2, y1);
-
- glEnd();
-}
-
-
/* ******************************************** */
void setlinestyle(int nr)
@@ -151,45 +82,12 @@ void set_inverted_drawing(int enable)
GL_TOGGLE(GL_DITHER, !enable);
}
-
-void glutil_draw_filled_arc(float start, float angle, float radius, int nsegments)
-{
- /* DEPRECATED */
- int i;
-
- glBegin(GL_TRIANGLE_FAN);
- glVertex2f(0.0, 0.0);
- for (i = 0; i < nsegments; i++) {
- float t = (float) i / (nsegments - 1);
- float cur = start + t * angle;
-
- glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
- }
- glEnd();
-}
-
-void glutil_draw_lined_arc(float start, float angle, float radius, int nsegments)
-{
- /* DEPRECATED */
- int i;
-
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < nsegments; i++) {
- float t = (float) i / (nsegments - 1);
- float cur = start + t * angle;
-
- glVertex2f(cosf(cur) * radius, sinf(cur) * radius);
- }
- glEnd();
-}
-
static void imm_draw_circle(PrimitiveType prim_type, unsigned pos, float x, float y, float rad, int nsegments)
{
immBegin(prim_type, nsegments);
for (int i = 0; i < nsegments; ++i) {
float angle = 2 * M_PI * ((float)i / (float)nsegments);
- immVertex2f(pos, x + rad * cosf(angle),
- y + rad * sinf(angle));
+ immVertex2f(pos, x + rad * cosf(angle), y + rad * sinf(angle));
}
immEnd();
}
@@ -204,6 +102,28 @@ void imm_draw_filled_circle(unsigned pos, float x, float y, float rad, int nsegm
imm_draw_circle(PRIM_TRIANGLE_FAN, pos, x, y, rad, nsegments);
}
+/**
+ * \note We could have `imm_draw_lined_disk_partial` but currently there is no need.
+ */
+static void imm_draw_disk_partial(
+ PrimitiveType prim_type, unsigned pos, float x, float y,
+ float rad_inner, float rad_outer, int nsegments, float start, float sweep)
+{
+ /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */
+ const float angle_start = -(DEG2RADF(start)) + (M_PI / 2);
+ const float angle_end = -(DEG2RADF(sweep) - angle_start);
+ nsegments += 1;
+ immBegin(prim_type, nsegments * 2);
+ for (int i = 0; i < nsegments; ++i) {
+ const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1)));
+ const float angle_sin = sinf(angle);
+ const float angle_cos = cosf(angle);
+ immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin);
+ immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin);
+ }
+ immEnd();
+}
+
static void imm_draw_circle_3D(GLenum prim_type, unsigned pos, float x, float y, float rad, int nsegments)
{
immBegin(prim_type, nsegments);
@@ -254,14 +174,6 @@ void imm_draw_line_box(unsigned pos, float x1, float y1, float x2, float y2)
immEnd();
}
-void imm_draw_line(unsigned pos, float x1, float y1, float x2, float y2)
-{
- immBegin(PRIM_LINES, 2);
- immVertex2f(pos, x1, y1);
- immVertex2f(pos, x2, y2);
- immEnd();
-}
-
void imm_draw_line_box_3D(unsigned pos, float x1, float y1, float x2, float y2)
{
/* use this version when VertexFormat has a vec3 position */
@@ -273,11 +185,151 @@ void imm_draw_line_box_3D(unsigned pos, float x1, float y1, float x2, float y2)
immEnd();
}
+void imm_draw_checker_box(float x1, float y1, float x2, float y2)
+{
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_CHECKER);
+
+ immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f);
+ immUniform4f("color2", 0.2f, 0.2f, 0.2f, 1.0f);
+ immUniform1i("size", 8);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+}
+
void imm_cpack(unsigned int x)
{
- immUniformColor3ub(((x)& 0xFF),
- (((x) >> 8) & 0xFF),
- (((x) >> 16) & 0xFF));
+ immUniformColor3ub(((x) & 0xFF),
+ (((x) >> 8) & 0xFF),
+ (((x) >> 16) & 0xFF));
+}
+
+void imm_cylinder_nor(unsigned int pos, unsigned int nor, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GL_TRIANGLES, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = 2 * M_PI * ((float)i / (float)slices);
+ const float angle2 = 2 * M_PI * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 *cos2, r1 * sin2, h1};
+ float v2[3] = {r2 *cos2, r2 * sin2, h2};
+ float v3[3] = {r2 *cos1, r2 * sin1, h2};
+ float v4[3] = {r1 *cos1, r1 * sin1, h1};
+ float n1[3], n2[3];
+
+ /* calc normals */
+ sub_v3_v3v3(n1, v2, v1);
+ normalize_v3(n1);
+ n1[0] = cos1; n1[1] = sin1; n1[2] = 1 - n1[2];
+
+ sub_v3_v3v3(n2, v3, v4);
+ normalize_v3(n2);
+ n2[0] = cos2; n2[1] = sin2; n2[2] = 1 - n2[2];
+
+ /* first tri */
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immAttrib3fv(nor, n1);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immAttrib3fv(nor, n2);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
+}
+
+void imm_cylinder_wire(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GL_LINES, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = 2 * M_PI * ((float)i / (float)slices);
+ const float angle2 = 2 * M_PI * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ }
+ }
+ immEnd();
+}
+
+void imm_cylinder(unsigned int pos, float base, float top, float height, int slices, int stacks)
+{
+ immBegin(GL_TRIANGLES, 6 * slices * stacks);
+ for (int i = 0; i < slices; ++i) {
+ const float angle1 = 2 * M_PI * ((float)i / (float)slices);
+ const float angle2 = 2 * M_PI * ((float)(i + 1) / (float)slices);
+ const float cos1 = cosf(angle1);
+ const float sin1 = sinf(angle1);
+ const float cos2 = cosf(angle2);
+ const float sin2 = sinf(angle2);
+
+ for (int j = 0; j < stacks; ++j) {
+ float fac1 = (float)j / (float)stacks;
+ float fac2 = (float)(j + 1) / (float)stacks;
+ float r1 = base * (1.f - fac1) + top * fac1;
+ float r2 = base * (1.f - fac2) + top * fac2;
+ float h1 = height * ((float)j / (float)stacks);
+ float h2 = height * ((float)(j + 1) / (float)stacks);
+
+ float v1[3] = {r1 * cos2, r1 * sin2, h1};
+ float v2[3] = {r2 * cos2, r2 * sin2, h2};
+ float v3[3] = {r2 * cos1, r2 * sin1, h2};
+ float v4[3] = {r1 * cos1, r1 * sin1, h1};
+
+ /* first tri */
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v2);
+ immVertex3fv(pos, v3);
+
+ /* second tri */
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v1);
+ }
+ }
+ immEnd();
}
float glaGetOneFloat(int param)
@@ -335,274 +387,34 @@ static int get_cached_work_texture(int *r_w, int *r_h)
return texid;
}
-/* DEPRECATED: use immDrawPixelsTexScaled_clipping instead */
-void glaDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float scaleX, float scaleY,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
+/* To be used before calling immDrawPixelsTex
+ * Default shader is GPU_SHADER_2D_IMAGE_COLOR
+ * You can still set uniforms with :
+ * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);
+ * */
+GPUShader *immDrawPixelsTexSetup(int builtin)
{
- unsigned char *uc_rect = (unsigned char *) rect;
- const float *f_rect = (float *)rect;
- float xzoom = glaGetOneFloat(GL_ZOOM_X), yzoom = glaGetOneFloat(GL_ZOOM_Y);
- int subpart_x, subpart_y, tex_w, tex_h;
- int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y;
- int texid = get_cached_work_texture(&tex_w, &tex_h);
- int components;
- const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
-
- /* Specify the color outside this function, and tex will modulate it.
- * This is useful for changing alpha without using glPixelTransferf()
- */
- glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
- glBindTexture(GL_TEXTURE_2D, texid);
-
- /* don't want nasty border artifacts */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter);
-
- /* setup seamless 2=on, 0=off */
- seamless = ((tex_w < img_w || tex_h < img_h) && tex_w > 2 && tex_h > 2) ? 2 : 0;
-
- offset_x = tex_w - seamless;
- offset_y = tex_h - seamless;
-
- nsubparts_x = (img_w + (offset_x - 1)) / (offset_x);
- nsubparts_y = (img_h + (offset_y - 1)) / (offset_y);
+ GPUShader *shader = GPU_shader_get_builtin_shader(builtin);
+ /* Shader will be unbind by immUnbindProgram in immDrawPixelsTexScaled_clipping */
+ GPU_shader_bind(shader);
+ GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "image"), 0);
- if (format == GL_RGBA)
- components = 4;
- else if (format == GL_RGB)
- components = 3;
- else if (ELEM(format, GL_LUMINANCE, GL_ALPHA))
- components = 1;
- else {
- BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled");
- return;
- }
-
- if (type == GL_FLOAT) {
- /* need to set internal format to higher range float */
-
- /* NOTE: this could fail on some drivers, like mesa,
- * but currently this code is only used by color
- * management stuff which already checks on whether
- * it's possible to use GL_RGBA16F_ARB
- */
-
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL);
- }
- else {
- /* switch to 8bit RGBA for byte buffer */
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL);
- }
-
- for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
- for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
- int remainder_x = img_w - subpart_x * offset_x;
- int remainder_y = img_h - subpart_y * offset_y;
- int subpart_w = (remainder_x < tex_w) ? remainder_x : tex_w;
- int subpart_h = (remainder_y < tex_h) ? remainder_y : tex_h;
- int offset_left = (seamless && subpart_x != 0) ? 1 : 0;
- int offset_bot = (seamless && subpart_y != 0) ? 1 : 0;
- int offset_right = (seamless && remainder_x > tex_w) ? 1 : 0;
- int offset_top = (seamless && remainder_y > tex_h) ? 1 : 0;
- float rast_x = x + subpart_x * offset_x * xzoom;
- float rast_y = y + subpart_y * offset_y * yzoom;
- /* check if we already got these because we always get 2 more when doing seamless */
- if (subpart_w <= seamless || subpart_h <= seamless)
- continue;
-
- if (use_clipping) {
- if (rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX < clip_min_x ||
- rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY < clip_min_y)
- {
- continue;
- }
- if (rast_x + (float)offset_left * xzoom > clip_max_x ||
- rast_y + (float)offset_bot * yzoom > clip_max_y)
- {
- continue;
- }
- }
-
- if (type == GL_FLOAT) {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
-
- /* add an extra border of pixels so linear looks ok at edges of full image */
- if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
- if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- }
- else {
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + subpart_x * offset_x * components]);
-
- if (subpart_w < tex_w)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[((size_t)subpart_y) * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- if (subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]);
- if (subpart_w < tex_w && subpart_h < tex_h)
- glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(((size_t)subpart_y) * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]);
- }
-
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
- glBegin(GL_QUADS);
- glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom);
-
- glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h);
- glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom);
-
- glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
-
- glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(subpart_h - offset_top) / tex_h);
- glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY);
- glEnd();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
- }
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-}
-
-/* DEPRECATED: use immDrawPixelsTexScaled instead */
-void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float scaleX, float scaleY)
-{
- glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- scaleX, scaleY, 0.0f, 0.0f, 0.0f, 0.0f);
-}
-
-/* DEPRECATED: use immDrawPixelsTex instead */
-void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
-{
- glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
- 0.0f, 0.0f, 0.0f, 0.0f);
-}
-
-/* DEPRECATED: use immDrawPixelsTex_clipping instead */
-void glaDrawPixelsTex_clipping(float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y, float clip_max_x, float clip_max_y)
-{
- glaDrawPixelsTexScaled_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ return shader;
}
-void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect)
-{
- float xzoom = glaGetOneFloat(GL_ZOOM_X);
- float yzoom = glaGetOneFloat(GL_ZOOM_Y);
-
- /* The pixel space coordinate of the intersection of
- * the [zoomed] image with the origin.
- */
- float ix = -x / xzoom;
- float iy = -y / yzoom;
-
- /* The maximum pixel amounts the image can be cropped
- * at the lower left without exceeding the origin.
- */
- int off_x = floor(max_ff(ix, 0.0f));
- int off_y = floor(max_ff(iy, 0.0f));
-
- /* The zoomed space coordinate of the raster position
- * (starting at the lower left most unclipped pixel).
- */
- float rast_x = x + off_x * xzoom;
- float rast_y = y + off_y * yzoom;
-
- GLfloat scissor[4];
- int draw_w, draw_h;
-
- /* Determine the smallest number of pixels we need to draw
- * before the image would go off the upper right corner.
- *
- * It may seem this is just an optimization but some graphics
- * cards (ATI) freak out if there is a large zoom factor and
- * a large number of pixels off the screen (probably at some
- * level the number of image pixels to draw is getting multiplied
- * by the zoom and then clamped). Making sure we draw the
- * fewest pixels possible keeps everyone mostly happy (still
- * fails if we zoom in on one really huge pixel so that it
- * covers the entire screen).
- */
- glGetFloatv(GL_SCISSOR_BOX, scissor);
- draw_w = min_ii(img_w - off_x, ceil((scissor[2] - rast_x) / xzoom));
- draw_h = min_ii(img_h - off_y, ceil((scissor[3] - rast_y) / yzoom));
-
- if (draw_w > 0 && draw_h > 0) {
-
- int bound_options;
- GPU_BASIC_SHADER_DISABLE_AND_STORE(bound_options);
-
- /* Don't use safe RasterPos (slower) if we can avoid it. */
- if (rast_x >= 0 && rast_y >= 0) {
- glRasterPos2f(rast_x, rast_y);
- }
- else {
- glaRasterPosSafe2f(rast_x, rast_y, 0, 0);
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, row_w);
- if (format == GL_LUMINANCE || format == GL_RED) {
- if (type == GL_FLOAT) {
- const float *f_rect = (float *)rect;
- glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x));
- }
- else if (type == GL_INT || type == GL_UNSIGNED_INT) {
- const int *i_rect = (int *)rect;
- glDrawPixels(draw_w, draw_h, format, type, i_rect + (off_y * row_w + off_x));
- }
- }
- else { /* RGBA */
- if (type == GL_FLOAT) {
- const float *f_rect = (float *)rect;
- glDrawPixels(draw_w, draw_h, format, type, f_rect + (off_y * row_w + off_x) * 4);
- }
- else if (type == GL_UNSIGNED_BYTE) {
- unsigned char *uc_rect = (unsigned char *) rect;
- glDrawPixels(draw_w, draw_h, format, type, uc_rect + (off_y * row_w + off_x) * 4);
- }
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
-
- GPU_BASIC_SHADER_ENABLE_AND_RESTORE(bound_options);
- }
-}
-
-/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */
-void glaDrawPixelsAuto_clipping(float x, float y, int img_w, int img_h,
- int format, int type, int zoomfilter, void *rect,
- float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
-{
- if (U.image_draw_method != IMAGE_DRAW_METHOD_DRAWPIXELS) {
- glColor4f(1.0, 1.0, 1.0, 1.0);
- glaDrawPixelsTex_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
- }
- else {
- glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect);
- }
-}
-
-void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect)
-{
- glaDrawPixelsAuto_clipping(x, y, img_w, img_h, format, type, zoomfilter, rect,
- 0.0f, 0.0f, 0.0f, 0.0f);
-}
-
-/* TODO this is utterly slow and need some love
- * but in the meantime it's not using deprecated api */
+/* Use the currently bound shader.
+ *
+ * Use immDrawPixelsTexSetup to bind the shader you
+ * want before calling immDrawPixelsTex.
+ *
+ * If using a special shader double check it uses the same
+ * attributes "pos" "texCoord" and uniform "image".
+ *
+ * If color is NULL then use white by default
+ *
+ * Be also aware that this function unbinds the shader when
+ * it's finished.
+ * */
void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
int format, int type, int zoomfilter, void *rect,
float scaleX, float scaleY,
@@ -617,10 +429,11 @@ void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
int texid = get_cached_work_texture(&tex_w, &tex_h);
int components;
const bool use_clipping = ((clip_min_x < clip_max_x) && (clip_min_y < clip_max_y));
+ float white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ GLint unpack_row_length;
+ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &unpack_row_length);
- /* Specify the color outside this function, and tex will modulate it.
- * This is useful for changing alpha without using glPixelTransferf()
- */
glPixelStorei(GL_UNPACK_ROW_LENGTH, img_w);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -670,9 +483,21 @@ void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
unsigned int pos = add_attrib(vert_format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned int texco = add_attrib(vert_format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
- immUniform4fv("color", color);
- immUniform1i("image", 0);
+ unsigned int program = glaGetOneInt(GL_CURRENT_PROGRAM);
+
+ /* This is needed for the OCIO case.
+ * Shader program is set outside of blender and
+ * we need it in imm module to do all attrib /
+ * uniform bindings. */
+
+ /* A program is already bound.
+ * set it in imm.bound_program to be able to use imm functions */
+ BLI_assert(program);
+ immBindProgram(program);
+
+ /* optionnal */
+ if (glGetUniformLocation(program, "color") != -1)
+ immUniform4fv("color", (color) ? color : white);
for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) {
for (subpart_x = 0; subpart_x < nsubparts_x; subpart_x++) {
@@ -744,7 +569,7 @@ void immDrawPixelsTexScaled_clipping(float x, float y, int img_w, int img_h,
immUnbindProgram();
glBindTexture(GL_TEXTURE_2D, 0);
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length);
}
void immDrawPixelsTexScaled(float x, float y, int img_w, int img_h,
@@ -787,13 +612,18 @@ void glaDefine2DArea(rcti *screen_rect)
* Programming Guide, Appendix H, Correctness Tips.
*/
+#if 1 /* new style */
+ gpuOrtho2D(GLA_PIXEL_OFS, sc_w + GLA_PIXEL_OFS, GLA_PIXEL_OFS, sc_h + GLA_PIXEL_OFS);
+ gpuLoadIdentity();
+#else /* original */
glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ gpuLoadIdentity();
glOrtho(0.0, sc_w, 0.0, sc_h, -1, 1);
- glTranslatef(GLA_PIXEL_OFS, GLA_PIXEL_OFS, 0.0);
+ gpuTranslate2f(GLA_PIXEL_OFS, GLA_PIXEL_OFS);
glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ gpuLoadIdentity();
+#endif
}
/* TODO(merwin): put the following 2D code to use, or build new 2D code inspired & informd by it */
@@ -851,8 +681,8 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect)
glGetIntegerv(GL_VIEWPORT, (GLint *)di->orig_vp);
glGetIntegerv(GL_SCISSOR_BOX, (GLint *)di->orig_sc);
- glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat *)di->orig_projmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)di->orig_viewmat);
+ gpuGetProjectionMatrix3D(di->orig_projmat);
+ gpuGetModelViewMatrix3D(di->orig_viewmat);
di->screen_rect = *screen_rect;
if (world_rect) {
@@ -903,10 +733,8 @@ void glaEnd2DDraw(gla2DDrawInfo *di)
{
glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
glScissor(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(di->orig_projmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(di->orig_viewmat);
+ gpuLoadProjectionMatrix3D(di->orig_projmat);
+ gpuLoadMatrix3D(di->orig_viewmat);
MEM_freeN(di);
}
@@ -914,33 +742,6 @@ void glaEnd2DDraw(gla2DDrawInfo *di)
#endif /* UNUSED */
-/* Uses current OpenGL state to get view matrices for gluProject/gluUnProject */
-void bgl_get_mats(bglMats *mats)
-{
- const double badvalue = 1.0e-6;
-
- glGetDoublev(GL_MODELVIEW_MATRIX, mats->modelview);
- glGetDoublev(GL_PROJECTION_MATRIX, mats->projection);
- glGetIntegerv(GL_VIEWPORT, (GLint *)mats->viewport);
-
- /* Very strange code here - it seems that certain bad values in the
- * modelview matrix can cause gluUnProject to give bad results. */
- if (mats->modelview[0] < badvalue &&
- mats->modelview[0] > -badvalue)
- {
- mats->modelview[0] = 0;
- }
- if (mats->modelview[5] < badvalue &&
- mats->modelview[5] > -badvalue)
- {
- mats->modelview[5] = 0;
- }
-
- /* Set up viewport so that gluUnProject will give correct values */
- mats->viewport[0] = 0;
- mats->viewport[1] = 0;
-}
-
/* *************** glPolygonOffset hack ************* */
/**
@@ -957,8 +758,7 @@ void bglPolygonOffset(float viewdist, float dist)
// glPolygonOffset(-1.0, -1.0);
/* hack below is to mimic polygon offset */
- glMatrixMode(GL_PROJECTION);
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)winmat);
+ gpuGetProjectionMatrix3D((float (*)[4])winmat);
/* dist is from camera to center point */
@@ -989,17 +789,13 @@ void bglPolygonOffset(float viewdist, float dist)
winmat[14] -= offs;
offset += offs;
-
- glLoadMatrixf(winmat);
- glMatrixMode(GL_MODELVIEW);
}
else {
- glMatrixMode(GL_PROJECTION);
winmat[14] += offset;
offset = 0.0;
- glLoadMatrixf(winmat);
- glMatrixMode(GL_MODELVIEW);
}
+
+ gpuLoadProjectionMatrix3D((const float (*)[4])winmat);
}
/* **** Color management helper functions for GLSL display/transform ***** */
@@ -1009,7 +805,8 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
ColorManagedViewSettings *view_settings,
ColorManagedDisplaySettings *display_settings,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y)
{
bool force_fallback = false;
bool need_fallback = true;
@@ -1046,8 +843,6 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
}
if (ok) {
- glColor4f(1.0, 1.0, 1.0, 1.0);
-
if (ibuf->rect_float) {
int format = 0;
@@ -1059,16 +854,18 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
BLI_assert(!"Incompatible number of channels for GLSL display");
if (format != 0) {
- glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
+ immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, format, GL_FLOAT,
zoomfilter, ibuf->rect_float,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
}
else if (ibuf->rect) {
/* ibuf->rect is always RGBA */
- glaDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
zoomfilter, ibuf->rect,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
IMB_colormanagement_finish_glsl_draw();
@@ -1085,9 +882,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
if (display_buffer) {
- glaDrawPixelsAuto_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
- zoomfilter, display_buffer,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE,
+ zoomfilter, display_buffer,
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y, NULL);
}
IMB_display_buffer_release(cache_handle);
@@ -1096,10 +895,11 @@ void glaDrawImBuf_glsl_clipping(ImBuf *ibuf, float x, float y, int zoomfilter,
void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter,
ColorManagedViewSettings *view_settings,
- ColorManagedDisplaySettings *display_settings)
+ ColorManagedDisplaySettings *display_settings,
+ float zoom_x, float zoom_y)
{
glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- 0.0f, 0.0f, 0.0f, 0.0f);
+ 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
}
void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
@@ -1107,7 +907,8 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
float x, float y,
int zoomfilter,
float clip_min_x, float clip_min_y,
- float clip_max_x, float clip_max_y)
+ float clip_max_x, float clip_max_y,
+ float zoom_x, float zoom_y)
{
ColorManagedViewSettings *view_settings;
ColorManagedDisplaySettings *display_settings;
@@ -1115,12 +916,14 @@ void glaDrawImBuf_glsl_ctx_clipping(const bContext *C,
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
glaDrawImBuf_glsl_clipping(ibuf, x, y, zoomfilter, view_settings, display_settings,
- clip_min_x, clip_min_y, clip_max_x, clip_max_y);
+ clip_min_x, clip_min_y, clip_max_x, clip_max_y,
+ zoom_x, zoom_y);
}
-void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter)
+void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter,
+ float zoom_x, float zoom_y)
{
- glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f);
+ glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, zoomfilter, 0.0f, 0.0f, 0.0f, 0.0f, zoom_x, zoom_y);
}
void cpack(unsigned int x)
@@ -1131,7 +934,7 @@ void cpack(unsigned int x)
(((x) >> 16) & 0xFF));
}
-void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
+void immDrawBorderCorners(unsigned int pos, const rcti *border, float zoomx, float zoomy)
{
float delta_x = 4.0f * UI_DPI_FAC / zoomx;
float delta_y = 4.0f * UI_DPI_FAC / zoomy;
@@ -1140,30 +943,30 @@ void glaDrawBorderCorners(const rcti *border, float zoomx, float zoomy)
delta_y = min_ff(delta_y, border->ymax - border->ymin);
/* left bottom corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmin, border->ymin + delta_y);
- glVertex2f(border->xmin, border->ymin);
- glVertex2f(border->xmin + delta_x, border->ymin);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymin + delta_y);
+ immVertex2f(pos, border->xmin, border->ymin);
+ immVertex2f(pos, border->xmin + delta_x, border->ymin);
+ immEnd();
/* left top corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmin, border->ymax - delta_y);
- glVertex2f(border->xmin, border->ymax);
- glVertex2f(border->xmin + delta_x, border->ymax);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmin, border->ymax - delta_y);
+ immVertex2f(pos, border->xmin, border->ymax);
+ immVertex2f(pos, border->xmin + delta_x, border->ymax);
+ immEnd();
/* right bottom corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmax - delta_x, border->ymin);
- glVertex2f(border->xmax, border->ymin);
- glVertex2f(border->xmax, border->ymin + delta_y);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin);
+ immVertex2f(pos, border->xmax, border->ymin + delta_y);
+ immEnd();
/* right top corner */
- glBegin(GL_LINE_STRIP);
- glVertex2f(border->xmax - delta_x, border->ymax);
- glVertex2f(border->xmax, border->ymax);
- glVertex2f(border->xmax, border->ymax - delta_y);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2f(pos, border->xmax - delta_x, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax);
+ immVertex2f(pos, border->xmax, border->ymax - delta_y);
+ immEnd();
}
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index c82a210725c..0448fba78e6 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -97,7 +97,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "visible_objects")) {
- Object *ob;
FOREACH_VISIBLE_OBJECT(sl, ob)
{
CTX_data_id_list_add(result, &ob->id);
@@ -116,7 +115,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_objects")) {
- Object *ob;
FOREACH_SELECTED_OBJECT(sl, ob)
{
CTX_data_id_list_add(result, &ob->id);
@@ -126,7 +124,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if (CTX_data_equals(member, "selected_editable_objects")) {
- Object *ob;
FOREACH_SELECTED_OBJECT(sl, ob)
{
if (0 == BKE_object_is_libdata(ob)) {
@@ -139,7 +136,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
}
else if (CTX_data_equals(member, "editable_objects")) {
/* Visible + Editable, but not necessarily selected */
- Object *ob;
FOREACH_VISIBLE_OBJECT(sl, ob)
{
if (0 == BKE_object_is_libdata(ob)) {
@@ -151,7 +147,6 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
return 1;
}
else if ( CTX_data_equals(member, "visible_bases")) {
- Base *base;
FOREACH_VISIBLE_BASE(sl, base)
{
CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
diff --git a/source/blender/editors/screen/screen_draw.c b/source/blender/editors/screen/screen_draw.c
index f73bed16330..bbcf4eb56a2 100644
--- a/source/blender/editors/screen/screen_draw.c
+++ b/source/blender/editors/screen/screen_draw.c
@@ -26,6 +26,7 @@
#include "GPU_framebuffer.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -34,9 +35,9 @@
/**
- * Draw vertical shape visualizing future joining (left as well right direction of future joining).
+ * Draw horizontal shape visualizing future joining (left as well right direction of future joining).
*/
-static void draw_horizontal_join_shape(ScrArea *sa, char dir)
+static void draw_horizontal_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
vec2f points[10];
short i;
@@ -93,24 +94,31 @@ static void draw_horizontal_join_shape(ScrArea *sa, char dir)
}
}
- glBegin(GL_POLYGON);
- for (i = 0; i < 5; i++)
- glVertex2f(points[i].x, points[i].y);
- glEnd();
- glBegin(GL_POLYGON);
- for (i = 4; i < 8; i++)
- glVertex2f(points[i].x, points[i].y);
- glVertex2f(points[0].x, points[0].y);
- glEnd();
-
- glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
- glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
+ immBegin(GL_TRIANGLE_FAN, 5);
+
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immEnd();
+
+ immBegin(GL_TRIANGLE_FAN, 5);
+
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
+
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
* Draw vertical shape visualizing future joining (up/down direction).
*/
-static void draw_vertical_join_shape(ScrArea *sa, char dir)
+static void draw_vertical_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
vec2f points[10];
short i;
@@ -167,91 +175,117 @@ static void draw_vertical_join_shape(ScrArea *sa, char dir)
}
}
- glBegin(GL_POLYGON);
- for (i = 0; i < 5; i++)
- glVertex2f(points[i].x, points[i].y);
- glEnd();
- glBegin(GL_POLYGON);
- for (i = 4; i < 8; i++)
- glVertex2f(points[i].x, points[i].y);
- glVertex2f(points[0].x, points[0].y);
- glEnd();
-
- glRectf(points[2].x, points[2].y, points[8].x, points[8].y);
- glRectf(points[6].x, points[6].y, points[9].x, points[9].y);
+ immBegin(GL_TRIANGLE_FAN, 5);
+
+ for (i = 0; i < 5; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immEnd();
+
+ immBegin(GL_TRIANGLE_FAN, 5);
+
+ for (i = 4; i < 8; i++) {
+ immVertex2f(pos, points[i].x, points[i].y);
+ }
+
+ immVertex2f(pos, points[0].x, points[0].y);
+ immEnd();
+
+ immRectf(pos, points[2].x, points[2].y, points[8].x, points[8].y);
+ immRectf(pos, points[6].x, points[6].y, points[9].x, points[9].y);
}
/**
* Draw join shape due to direction of joining.
*/
-static void draw_join_shape(ScrArea *sa, char dir)
+static void draw_join_shape(ScrArea *sa, char dir, unsigned int pos)
{
- if (dir == 'u' || dir == 'd')
- draw_vertical_join_shape(sa, dir);
- else
- draw_horizontal_join_shape(sa, dir);
+ if (dir == 'u' || dir == 'd') {
+ draw_vertical_join_shape(sa, dir, pos);
+ }
+ else {
+ draw_horizontal_join_shape(sa, dir, pos);
+ }
}
/**
* Draw screen area darker with arrow (visualization of future joining).
*/
-static void scrarea_draw_shape_dark(ScrArea *sa, char dir)
+static void scrarea_draw_shape_dark(ScrArea *sa, char dir, unsigned int pos)
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4ub(0, 0, 0, 50);
- draw_join_shape(sa, dir);
+ immUniformColor4ub(0, 0, 0, 50);
+
+ draw_join_shape(sa, dir, pos);
}
/**
* Draw screen area ligher with arrow shape ("eraser" of previous dark shape).
*/
-static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir))
+static void scrarea_draw_shape_light(ScrArea *sa, char UNUSED(dir), unsigned int pos)
{
glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
/* value 181 was hardly computed: 181~105 */
- glColor4ub(255, 255, 255, 50);
+ immUniformColor4ub(255, 255, 255, 50);
/* draw_join_shape(sa, dir); */
- glRecti(sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
+
+ immRectf(pos, sa->v1->vec.x, sa->v1->vec.y, sa->v3->vec.x, sa->v3->vec.y);
}
-static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2)
+static void drawscredge_area_draw(int sizex, int sizey, short x1, short y1, short x2, short y2, unsigned int pos)
{
+ int count = 0;
+
+ if (x2 < sizex - 1) count += 2;
+ if (x1 > 0) count += 2;
+ if (y2 < sizey - 1) count += 2;
+ if (y1 > 0) count += 2;
+
+ if (count == 0) {
+ return;
+ }
+
+ immBegin(GL_LINES, count);
+
/* right border area */
if (x2 < sizex - 1) {
- glVertex2s(x2, y1);
- glVertex2s(x2, y2);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x2, y2);
}
/* left border area */
if (x1 > 0) { /* otherwise it draws the emboss of window over */
- glVertex2s(x1, y1);
- glVertex2s(x1, y2);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
}
/* top border area */
if (y2 < sizey - 1) {
- glVertex2s(x1, y2);
- glVertex2s(x2, y2);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
}
/* bottom border area */
if (y1 > 0) {
- glVertex2s(x1, y1);
- glVertex2s(x2, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x2, y1);
}
+
+ immEnd();
}
/**
* \brief Screen edges drawing.
*/
-static void drawscredge_area(ScrArea *sa, int sizex, int sizey)
+static void drawscredge_area(ScrArea *sa, int sizex, int sizey, unsigned int pos)
{
short x1 = sa->v1->vec.x;
short y1 = sa->v1->vec.y;
short x2 = sa->v3->vec.x;
short y2 = sa->v3->vec.y;
- drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2);
+ drawscredge_area_draw(sizex, sizey, x1, y1, x2, y2, pos);
}
/**
@@ -269,29 +303,31 @@ void ED_screen_draw(wmWindow *win)
wmSubWindowSet(win, win->screen->mainwin);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* Note: first loop only draws if U.pixelsize > 1, skip otherwise */
if (U.pixelsize > 1.0f) {
/* FIXME: doesn't our glLineWidth already scale by U.pixelsize? */
glLineWidth((2.0f * U.pixelsize) - 1);
- glColor3ub(0x50, 0x50, 0x50);
- glBegin(GL_LINES);
- for (sa = win->screen->areabase.first; sa; sa = sa->next)
- drawscredge_area(sa, winsize_x, winsize_y);
- glEnd();
+ immUniformColor3ub(0x50, 0x50, 0x50);
+
+ for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+ drawscredge_area(sa, winsize_x, winsize_y, pos);
+ }
}
glLineWidth(1);
- glColor3ub(0, 0, 0);
- glBegin(GL_LINES);
+ immUniformColor3ub(0, 0, 0);
+
for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- drawscredge_area(sa, winsize_x, winsize_y);
+ drawscredge_area(sa, winsize_x, winsize_y, pos);
/* gather area split/join info */
if (sa->flag & AREA_FLAG_DRAWJOINFROM) sa1 = sa;
if (sa->flag & AREA_FLAG_DRAWJOINTO) sa2 = sa;
if (sa->flag & (AREA_FLAG_DRAWSPLIT_H | AREA_FLAG_DRAWSPLIT_V)) sa3 = sa;
}
- glEnd();
/* blended join arrow */
if (sa1 && sa2) {
@@ -317,36 +353,56 @@ void ED_screen_draw(wmWindow *win)
break;
}
}
+
glEnable(GL_BLEND);
- scrarea_draw_shape_dark(sa2, dir);
- scrarea_draw_shape_light(sa1, dira);
+
+ scrarea_draw_shape_dark(sa2, dir, pos);
+ scrarea_draw_shape_light(sa1, dira, pos);
+
glDisable(GL_BLEND);
}
/* splitpoint */
if (sa3) {
glEnable(GL_BLEND);
- glBegin(GL_LINES);
- glColor4ub(255, 255, 255, 100);
+ immUniformColor4ub(255, 255, 255, 100);
+
+ immBegin(GL_LINES, 2);
if (sa3->flag & AREA_FLAG_DRAWSPLIT_H) {
- glVertex2s(sa3->totrct.xmin, win->eventstate->y);
- glVertex2s(sa3->totrct.xmax, win->eventstate->y);
- glColor4ub(0, 0, 0, 100);
- glVertex2s(sa3->totrct.xmin, win->eventstate->y + 1);
- glVertex2s(sa3->totrct.xmax, win->eventstate->y + 1);
+ immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y);
+ immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y);
+
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 100);
+
+ immBegin(GL_LINES, 2);
+
+ immVertex2f(pos, sa3->totrct.xmin, win->eventstate->y + 1);
+ immVertex2f(pos, sa3->totrct.xmax, win->eventstate->y + 1);
}
else {
- glVertex2s(win->eventstate->x, sa3->totrct.ymin);
- glVertex2s(win->eventstate->x, sa3->totrct.ymax);
- glColor4ub(0, 0, 0, 100);
- glVertex2s(win->eventstate->x + 1, sa3->totrct.ymin);
- glVertex2s(win->eventstate->x + 1, sa3->totrct.ymax);
+ immVertex2f(pos, win->eventstate->x, sa3->totrct.ymin);
+ immVertex2f(pos, win->eventstate->x, sa3->totrct.ymax);
+
+ immEnd();
+
+ immUniformColor4ub(0, 0, 0, 100);
+
+ immBegin(GL_LINES, 2);
+
+ immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymin);
+ immVertex2f(pos, win->eventstate->x + 1, sa3->totrct.ymax);
}
- glEnd();
+
+ immEnd();
+
glDisable(GL_BLEND);
}
+ immUnbindProgram();
+
win->screen->do_draw = false;
}
@@ -377,16 +433,17 @@ static void screen_preview_draw_areas(const bScreen *screen, const float scale[2
{
const float ofs_h = ofs_between_areas * 0.5f;
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- rctf rect;
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4fv(col);
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
- rect.xmin = sa->totrct.xmin * scale[0] + ofs_h;
- rect.xmax = sa->totrct.xmax * scale[0] - ofs_h;
- rect.ymin = sa->totrct.ymin * scale[1] + ofs_h;
- rect.ymax = sa->totrct.ymax * scale[1] - ofs_h;
+ rctf rect = {
+ .xmin = sa->totrct.xmin * scale[0] + ofs_h,
+ .xmax = sa->totrct.xmax * scale[0] - ofs_h,
+ .ymin = sa->totrct.ymin * scale[1] + ofs_h,
+ .ymax = sa->totrct.ymax * scale[1] - ofs_h
+ };
immBegin(PRIM_TRIANGLE_FAN, 4);
immVertex2f(pos, rect.xmin, rect.ymin);
@@ -408,10 +465,13 @@ static void screen_preview_draw(const bScreen *screen, int size_x, int size_y)
wmOrtho2(0.0f, size_x, 0.0f, size_y);
/* center */
- glTranslatef(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(size_x * (1.0f - asp[0]) * 0.5f, size_y * (1.0f - asp[1]) * 0.5f);
screen_preview_scale_get(screen, size_x, size_y, asp, scale);
screen_preview_draw_areas(screen, scale, col, 1.5f);
+
+ gpuPopMatrix();
}
/**
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index a55d6c2143f..4ba3a534b49 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -321,10 +321,6 @@ int ED_operator_info_active(bContext *C)
return ed_spacetype_test(C, SPACE_INFO);
}
-int ED_operator_collections_active(bContext *C)
-{
- return ed_spacetype_test(C, SPACE_COLLECTIONS);
-}
int ED_operator_console_active(bContext *C)
{
@@ -576,8 +572,8 @@ int ED_operator_mask(bContext *C)
case SPACE_IMAGE:
{
SpaceImage *sima = sa->spacedata.first;
- Scene *scene = CTX_data_scene(C);
- return ED_space_image_check_show_maskedit(scene, sima);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ return ED_space_image_check_show_maskedit(sl, sima);
}
}
}
@@ -2817,7 +2813,7 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
bScreen *sc = CTX_wm_screen(C);
uiPopupMenu *pup;
uiLayout *layout;
- PointerRNA ptr1, ptr2;
+ PointerRNA ptr;
ScrEdge *actedge;
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -2829,22 +2825,17 @@ static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent
pup = UI_popup_menu_begin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- WM_operator_properties_create(&ptr1, "SCREEN_OT_area_join");
-
- /* mouse cursor on edge, '4' can fail on wide edges... */
- RNA_int_set(&ptr1, "min_x", event->x + 4);
- RNA_int_set(&ptr1, "min_y", event->y + 4);
- RNA_int_set(&ptr1, "max_x", event->x - 4);
- RNA_int_set(&ptr1, "max_y", event->y - 4);
-
- WM_operator_properties_create(&ptr2, "SCREEN_OT_area_split");
-
+ ptr = uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
/* store initial mouse cursor position */
- RNA_int_set(&ptr2, "mouse_x", event->x);
- RNA_int_set(&ptr2, "mouse_y", event->y);
-
- uiItemFullO(layout, "SCREEN_OT_area_split", NULL, ICON_NONE, ptr2.data, WM_OP_INVOKE_DEFAULT, 0);
- uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, ptr1.data, WM_OP_INVOKE_DEFAULT, 0);
+ RNA_int_set(&ptr, "mouse_x", event->x);
+ RNA_int_set(&ptr, "mouse_y", event->y);
+
+ ptr = uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ /* mouse cursor on edge, '4' can fail on wide edges... */
+ RNA_int_set(&ptr, "min_x", event->x + 4);
+ RNA_int_set(&ptr, "min_y", event->y + 4);
+ RNA_int_set(&ptr, "max_x", event->x - 4);
+ RNA_int_set(&ptr, "max_y", event->y - 4);
UI_popup_menu_end(C, pup);
@@ -2912,10 +2903,23 @@ static void SCREEN_OT_spacedata_cleanup(wmOperatorType *ot)
static int repeat_last_exec(bContext *C, wmOperator *UNUSED(op))
{
- wmOperator *lastop = CTX_wm_manager(C)->operators.last;
-
- if (lastop)
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmOperator *lastop = wm->operators.last;
+
+ /* Seek last registered operator */
+ while (lastop) {
+ if (lastop->type->flag & OPTYPE_REGISTER) {
+ break;
+ }
+ else {
+ lastop = lastop->prev;
+ }
+ }
+
+ if (lastop) {
+ WM_operator_free_all_after(wm, lastop);
WM_operator_repeat(C, lastop);
+ }
return OPERATOR_CANCELLED;
}
@@ -2950,8 +2954,9 @@ static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
layout = UI_popup_menu_layout(pup);
for (i = items - 1, lastop = wm->operators.last; lastop; lastop = lastop->prev, i--)
- if (WM_operator_repeat_check(C, lastop))
+ if ((lastop->type->flag & OPTYPE_REGISTER) && WM_operator_repeat_check(C, lastop)) {
uiItemIntO(layout, RNA_struct_ui_name(lastop->type->srna), ICON_NONE, op->type->idname, "index", i);
+ }
UI_popup_menu_end(C, pup);
diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c
index 6bfa51bf9fc..5a8ea10cb0a 100644
--- a/source/blender/editors/screen/screendump.c
+++ b/source/blender/editors/screen/screendump.c
@@ -456,8 +456,8 @@ static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUS
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 53c11e2a6a9..0e18bddc45f 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -53,13 +53,14 @@
#include "WM_api.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "IMB_imbuf_types.h"
#include "ED_view3d.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_basic_shader.h"
#include "UI_resources.h"
@@ -605,21 +606,20 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
glDepthFunc(GL_ALWAYS);
glMatrixMode(GL_TEXTURE);
- glPushMatrix();
- glLoadIdentity();
+ glPushMatrix(); /* TEXTURE */
+ glLoadIdentity(); /* TEXTURE */
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* brush rotation */
- glTranslatef(0.5, 0.5, 0);
- glRotatef((double)RAD2DEGF((primary) ? ups->brush_rotation : ups->brush_rotation_sec),
- 0.0, 0.0, 1.0);
- glTranslatef(-0.5f, -0.5f, 0);
+ glTranslatef(0.5, 0.5, 0); /* TEXTURE */
+ glRotatef(RAD2DEGF(primary ? ups->brush_rotation : ups->brush_rotation_sec), 0, 0, 1); /* TEXTURE */
+ glTranslatef(-0.5f, -0.5f, 0); /* TEXTURE */
/* scale based on tablet pressure */
if (primary && ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
- glTranslatef(0.5f, 0.5f, 0);
- glScalef(1.0f / ups->size_pressure_value, 1.0f / ups->size_pressure_value, 1);
- glTranslatef(-0.5f, -0.5f, 0);
+ glTranslatef(0.5f, 0.5f, 0); /* TEXTURE */
+ glScalef(1.0f / ups->size_pressure_value, 1.0f / ups->size_pressure_value, 1.0f / ups->size_pressure_value); /* TEXTURE */
+ glTranslatef(-0.5f, -0.5f, 0); /* TEXTURE */
}
if (ups->draw_anchored) {
@@ -658,40 +658,50 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups, Brush *brush,
quad.ymax = brush->mask_stencil_dimension[1];
}
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuPushMatrix();
if (primary)
- glTranslate2fv(brush->stencil_pos);
+ gpuTranslate2fv(brush->stencil_pos);
else
- glTranslate2fv(brush->mask_stencil_pos);
- glRotatef(RAD2DEGF(mtex->rot), 0, 0, 1);
+ gpuTranslate2fv(brush->mask_stencil_pos);
+ gpuRotate2D(RAD2DEGF(mtex->rot));
glMatrixMode(GL_TEXTURE);
}
/* set quad color. Colored overlay does not get blending */
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+
if (col) {
- glColor4f(1.0, 1.0, 1.0, overlay_alpha / 100.0f);
+ immUniform4f("color", 1.0f, 1.0f, 1.0f, overlay_alpha / 100.0f);
}
else {
- glColor4f(UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f);
+ immUniform4f("color", UNPACK3(U.sculpt_paint_overlay_col), overlay_alpha / 100.0f);
}
/* draw textured quad */
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(quad.xmin, quad.ymin);
- glTexCoord2f(1, 0);
- glVertex2f(quad.xmax, quad.ymin);
- glTexCoord2f(1, 1);
- glVertex2f(quad.xmax, quad.ymax);
- glTexCoord2f(0, 1);
- glVertex2f(quad.xmin, quad.ymax);
- glEnd();
-
- glPopMatrix();
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GL_QUADS, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
+
+ glPopMatrix(); /* TEXTURE */
if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -739,32 +749,45 @@ static void paint_draw_cursor_overlay(UnifiedPaintSettings *ups, Brush *brush,
/* scale based on tablet pressure */
if (ups->stroke_active && BKE_brush_use_size_pressure(vc->scene, brush)) {
do_pop = true;
- glPushMatrix();
- glLoadIdentity();
- glTranslate2fv(center);
- glScalef(ups->size_pressure_value, ups->size_pressure_value, 1);
- glTranslatef(-center[0], -center[1], 0);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ gpuTranslate2fv(center);
+ gpuScaleUniform(ups->size_pressure_value);
+ gpuTranslate2f(-center[0], -center[1]);
}
- glColor4f(U.sculpt_paint_overlay_col[0],
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texCoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+
+ immUniform4f("color",
+ U.sculpt_paint_overlay_col[0],
U.sculpt_paint_overlay_col[1],
U.sculpt_paint_overlay_col[2],
brush->cursor_overlay_alpha / 100.0f);
/* draw textured quad */
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(quad.xmin, quad.ymin);
- glTexCoord2f(1, 0);
- glVertex2f(quad.xmax, quad.ymin);
- glTexCoord2f(1, 1);
- glVertex2f(quad.xmax, quad.ymax);
- glTexCoord2f(0, 1);
- glVertex2f(quad.xmin, quad.ymax);
- glEnd();
+
+ /* draw textured quad */
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GL_QUADS, 4);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, quad.xmin, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, quad.xmax, quad.ymin);
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, quad.xmax, quad.ymax);
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, quad.xmin, quad.ymax);
+ immEnd();
+
+ immUnbindProgram();
if (do_pop)
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -809,81 +832,102 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush,
}
-BLI_INLINE void draw_tri_point(float *co, float width, bool selected)
+BLI_INLINE void draw_tri_point(
+ unsigned int pos, float sel_col[4], float pivot_col[4],
+ float *co, float width, bool selected)
{
+ if (selected) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4fv(pivot_col);
+ }
+ glLineWidth(3.0f);
+
float w = width / 2.0f;
- if (selected)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- UI_ThemeColor4(TH_PAINT_CURVE_PIVOT);
-
- glLineWidth(3.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0], co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
-
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glLineWidth(1.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0], co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
+ float tri[3][2] = {
+ {co[0], co[1] + w},
+ {co[0] - w, co[1] - w},
+ {co[0] + w, co[1] - w},
+ };
+
+ immBegin(PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+
+ immBegin(PRIM_LINE_LOOP, 3);
+ immVertex2fv(pos, tri[0]);
+ immVertex2fv(pos, tri[1]);
+ immVertex2fv(pos, tri[2]);
+ immEnd();
}
-BLI_INLINE void draw_rect_point(float *co, float width, bool selected)
+BLI_INLINE void draw_rect_point(
+ unsigned int pos, float sel_col[4], float handle_col[4],
+ float *co, float width, bool selected)
{
+ if (selected) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4fv(handle_col);
+ }
+ glLineWidth(3.0f);
+
float w = width / 2.0f;
- if (selected)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- UI_ThemeColor4(TH_PAINT_CURVE_HANDLE);
- glLineWidth(3.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0] + w, co[1] + w);
- glVertex2f(co[0] - w, co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
-
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glLineWidth(1.0);
-
- glBegin(GL_LINE_LOOP);
- glVertex2f(co[0] + w, co[1] + w);
- glVertex2f(co[0] - w, co[1] + w);
- glVertex2f(co[0] - w, co[1] - w);
- glVertex2f(co[0] + w, co[1] - w);
- glEnd();
+ float minx = co[0] - w;
+ float miny = co[1] - w;
+ float maxx = co[0] + w;
+ float maxy = co[1] + w;
+
+ imm_draw_line_box(pos, minx, miny, maxx, maxy);
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+
+ imm_draw_line_box(pos, minx, miny, maxx, maxy);
}
-BLI_INLINE void draw_bezier_handle_lines(BezTriple *bez)
+BLI_INLINE void draw_bezier_handle_lines(unsigned int pos, float sel_col[4], BezTriple *bez)
{
- short line1[] = {0, 1};
- short line2[] = {1, 2};
-
- glVertexPointer(2, GL_FLOAT, 3 * sizeof(float), bez->vec);
- glColor4f(0.0, 0.0, 0.0, 0.5);
- glLineWidth(3.0);
- glDrawArrays(GL_LINE_STRIP, 0, 3);
-
- glLineWidth(1.0);
- if (bez->f1 || bez->f2)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line1);
- if (bez->f3 || bez->f2)
- UI_ThemeColor4(TH_VERTEX_SELECT);
- else
- glColor4f(1.0, 1.0, 1.0, 0.5);
- glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, line2);
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ glLineWidth(3.0f);
+
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
+
+ glLineWidth(1.0f);
+
+ if (bez->f1 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GL_LINES, 2);
+ immVertex2fv(pos, bez->vec[0]);
+ immVertex2fv(pos, bez->vec[1]);
+ immEnd();
+
+ if (bez->f3 || bez->f2) {
+ immUniformColor4fv(sel_col);
+ }
+ else {
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5f);
+ }
+ immBegin(GL_LINES, 2);
+ immVertex2fv(pos, bez->vec[1]);
+ immVertex2fv(pos, bez->vec[2]);
+ immEnd();
}
static void paint_draw_curve_cursor(Brush *brush)
@@ -895,18 +939,26 @@ static void paint_draw_curve_cursor(Brush *brush)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glEnableClientState(GL_VERTEX_ARRAY);
/* draw the bezier handles and the curve segment between the current and next point */
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ float selec_col[4], handle_col[4], pivot_col[4];
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, selec_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_HANDLE, handle_col);
+ UI_GetThemeColor4fv(TH_PAINT_CURVE_PIVOT, pivot_col);
+
for (i = 0; i < pc->tot_points - 1; i++, cp++) {
int j;
PaintCurvePoint *cp_next = cp + 1;
float data[(PAINT_CURVE_NUM_SEGMENTS + 1) * 2];
/* use color coding to distinguish handles vs curve segments */
- draw_bezier_handle_lines(&cp->bez);
- draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
- draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+ draw_bezier_handle_lines(pos, selec_col, &cp->bez);
+ draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
for (j = 0; j < 2; j++)
BKE_curve_forward_diff_bezier(
@@ -916,25 +968,35 @@ static void paint_draw_curve_cursor(Brush *brush)
cp_next->bez.vec[1][j],
data + j, PAINT_CURVE_NUM_SEGMENTS, sizeof(float[2]));
- glVertexPointer(2, GL_FLOAT, 0, data);
- glLineWidth(3.0);
- glColor4f(0.0, 0.0, 0.0, 0.5);
- glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ float (*v)[2] = (float(*)[2])data;
+
+ immUniformColor4f(0.0f, 0.0f, 0.0f, 0.5f);
+ glLineWidth(3.0f);
+ immBegin(GL_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
- glLineWidth(1.0);
- glColor4f(0.9, 0.9, 1.0, 0.5);
- glDrawArrays(GL_LINE_STRIP, 0, PAINT_CURVE_NUM_SEGMENTS + 1);
+ immUniformColor4f(0.9f, 0.9f, 1.0f, 0.5f);
+ glLineWidth(1.0f);
+ immBegin(GL_LINE_STRIP, PAINT_CURVE_NUM_SEGMENTS + 1);
+ for (j = 0; j <= PAINT_CURVE_NUM_SEGMENTS; j++) {
+ immVertex2fv(pos, v[j]);
+ }
+ immEnd();
}
/* draw last line segment */
- draw_bezier_handle_lines(&cp->bez);
- draw_tri_point(&cp->bez.vec[1][0], 10.0, cp->bez.f2);
- draw_rect_point(&cp->bez.vec[0][0], 8.0, cp->bez.f1 || cp->bez.f2);
- draw_rect_point(&cp->bez.vec[2][0], 8.0, cp->bez.f3 || cp->bez.f2);
+ draw_bezier_handle_lines(pos, selec_col, &cp->bez);
+ draw_tri_point(pos, selec_col, pivot_col, &cp->bez.vec[1][0], 10.0f, cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[0][0], 8.0f, cp->bez.f1 || cp->bez.f2);
+ draw_rect_point(pos, selec_col, handle_col, &cp->bez.vec[2][0], 8.0f, cp->bez.f3 || cp->bez.f2);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glDisableClientState(GL_VERTEX_ARRAY);
+
+ immUnbindProgram();
}
}
@@ -988,11 +1050,6 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
Paint *paint = BKE_paint_get_active_from_context(C);
Brush *brush = BKE_paint_brush(paint);
PaintMode mode = BKE_paintmode_get_active_from_context(C);
- ViewContext vc;
- float final_radius;
- float translation[2];
- float outline_alpha, *outline_col;
- float zoomx, zoomy;
/* check that brush drawing is enabled */
if (ommit_cursor_drawing(paint, mode, brush))
@@ -1000,8 +1057,10 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* can't use stroke vc here because this will be called during
* mouse over too, not just during a stroke */
+ ViewContext vc;
view3d_set_viewcontext(C, &vc);
+ float zoomx, zoomy;
get_imapaint_zoom(C, &zoomx, &zoomy);
zoomx = max_ff(zoomx, zoomy);
@@ -1012,11 +1071,10 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* set various defaults */
- translation[0] = x;
- translation[1] = y;
- outline_alpha = 0.5;
- outline_col = brush->add_col;
- final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
+ const float *outline_col = brush->add_col;
+ const float outline_alpha = 0.5f;
+ float translation[2] = { x, y };
+ float final_radius = (BKE_brush_size_get(scene, brush) * zoomx);
/* 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 */
@@ -1032,10 +1090,9 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
if ((mode == ePaintSculpt) && vc.obact->sculpt) {
float location[3];
int pixel_radius;
- bool hit;
/* test if brush is over the mesh */
- hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups);
+ bool hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location, ups);
if (BKE_brush_use_locked_size(scene, brush))
BKE_brush_size_set(scene, brush, pixel_radius);
@@ -1065,24 +1122,25 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* make lines pretty */
glLineWidth(1.0f);
- glEnable(GL_BLEND);
+ glEnable(GL_BLEND); /* TODO: also set blend mode? */
glEnable(GL_LINE_SMOOTH);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* set brush color */
- glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha);
+ immUniformColor3fvAlpha(outline_col, outline_alpha);
/* draw brush outline */
- glTranslate2fv(translation);
-
- /* draw an inner brush */
if (ups->stroke_active && BKE_brush_use_size_pressure(scene, brush)) {
/* inner at full alpha */
- glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius * ups->size_pressure_value, 40);
+ imm_draw_lined_circle(pos, translation[0], translation[1], final_radius * ups->size_pressure_value, 40);
/* outer at half alpha */
- glColor4f(outline_col[0], outline_col[1], outline_col[2], outline_alpha * 0.5f);
+ immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
}
- glutil_draw_lined_arc(0.0, M_PI * 2.0, final_radius, 40);
- glTranslatef(-translation[0], -translation[1], 0);
+ imm_draw_lined_circle(pos, translation[0], translation[1], final_radius, 40);
+
+ immUnbindProgram();
/* restore GL state */
glDisable(GL_BLEND);
diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c
index 5af6792f10f..5b5d91e8566 100644
--- a/source/blender/editors/sculpt_paint/paint_hide.c
+++ b/source/blender/editors/sculpt_paint/paint_hide.c
@@ -323,12 +323,10 @@ static void clip_planes_from_rect(bContext *C,
{
ViewContext vc;
BoundBox bb;
- bglMats mats = {{0}};
view3d_operator_needs_opengl(C);
view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, rect);
negate_m4(clip_planes);
}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index ffaaed8ab42..7ea1cac045c 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -722,8 +722,8 @@ static void gradient_draw_line(bContext *UNUSED(C), int x, int y, void *customda
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -765,7 +765,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
/* initialize from context */
if (CTX_wm_region_view3d(C)) {
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
bool uvs, mat, tex, stencil;
if (!BKE_paint_proj_mesh_data_check(scene, ob, &uvs, &mat, &tex, &stencil)) {
BKE_paint_data_warning(op->reports, uvs, mat, tex, stencil);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index f5d115442c6..6a020dbdab2 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -5305,11 +5305,12 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
{
Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image"));
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ProjPaintState ps = {NULL};
int orig_brush_size;
IDProperty *idgroup;
IDProperty *view_data = NULL;
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
bool uvs, mat, tex;
if (ob == NULL || ob->type != OB_MESH) {
@@ -5438,6 +5439,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
char filename[FILE_MAX];
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ToolSettings *settings = scene->toolsettings;
int w = settings->imapaint.screen_grab_size[0];
int h = settings->imapaint.screen_grab_size[1];
@@ -5452,7 +5454,7 @@ static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op)
if (h > maxsize) h = maxsize;
ibuf = ED_view3d_draw_offscreen_imbuf(
- scene, CTX_wm_view3d(C), CTX_wm_region(C),
+ scene, sl, CTX_wm_view3d(C), CTX_wm_region(C),
w, h, IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
NULL, NULL, err_out);
if (!ibuf) {
@@ -5711,21 +5713,16 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op)
/* successful creation of mtex layer, now create set */
if (mtex) {
int type = MAP_COL;
- int type_id = 0;
+ char imagename_buff[MAX_ID_NAME - 2];
+ const char *imagename = DATA_("Diffuse Color");
if (op) {
- int i;
type = RNA_enum_get(op->ptr, "type");
-
- for (i = 0; i < ARRAY_SIZE(layer_type_items); i++) {
- if (layer_type_items[i].value == type) {
- type_id = i;
- break;
- }
- }
+ RNA_string_get(op->ptr, "name", imagename_buff);
+ imagename = imagename_buff;
}
- mtex->tex = BKE_texture_add(bmain, DATA_(layer_type_items[type_id].name));
+ mtex->tex = BKE_texture_add(bmain, imagename);
mtex->mapto = type;
if (mtex->tex) {
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 7e05ab929ae..69c4621945b 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -209,7 +209,6 @@ bool paint_convert_bb_to_rect(struct rcti *rect,
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
const struct ARegion *ar,
- struct RegionView3D *rv3d,
struct Object *ob,
const struct rcti *screen_rect);
diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c
index a4887c579ac..b4938e0f7d8 100644
--- a/source/blender/editors/sculpt_paint/paint_mask.c
+++ b/source/blender/editors/sculpt_paint/paint_mask.c
@@ -251,7 +251,6 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
{
Sculpt *sd = vc->scene->toolsettings->sculpt;
BoundBox bb;
- bglMats mats = {{0}};
float clip_planes[4][4];
float clip_planes_final[4][4];
ARegion *ar = vc->ar;
@@ -269,8 +268,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r
value = select ? 1.0 : 0.0;
/* transform the clip planes in object space */
- view3d_get_transformation(vc->ar, vc->rv3d, vc->obact, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc->ar, vc->obact, rect);
negate_m4(clip_planes);
BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
@@ -411,7 +409,6 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
if (mcords) {
float clip_planes[4][4], clip_planes_final[4][4];
BoundBox bb;
- bglMats mats = {{0}};
Object *ob;
ViewContext vc;
LassoMaskData data;
@@ -429,7 +426,6 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
* calculations done. Bounding box PBVH collision is not computed against enclosing rectangle
* of lasso */
view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, vc.obact, &mats);
/* lasso data calculations */
data.vc = &vc;
@@ -445,7 +441,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op)
mcords, mcords_tot,
mask_lasso_px_cb, &data);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, &data.rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, vc.ar, vc.obact, &data.rect);
negate_m4(clip_planes);
BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 05270dbfa09..e6113f2c2c3 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -58,7 +58,7 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "ED_screen.h"
#include "ED_view3d.h"
@@ -145,9 +145,18 @@ static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata
if (stroke && brush) {
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glColor4ubv(paint->paint_cursor_col);
- sdrawline(x, y, (int)stroke->last_mouse_position[0],
- (int)stroke->last_mouse_position[1]);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor4ubv(paint->paint_cursor_col);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, x, y);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
@@ -161,32 +170,46 @@ static void paint_draw_line_cursor(bContext *C, int x, int y, void *customdata)
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- GPU_basic_shader_line_width(3.0);
+ setlinestyle(3);
+ glLineWidth(3.0f);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
+
+ immBegin(GL_LINES, 2);
- glColor4ub(0, 0, 0, paint->paint_cursor_col[3]);
if (stroke->constrain_line) {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(pos, stroke->constrained_pos[0], stroke->constrained_pos[1]);
}
else {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(pos, x, y);
}
- glColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
- GPU_basic_shader_line_width(1.0);
+ immEnd();
+
+ glLineWidth(1.0f);
+ immUniformColor4ub(255, 255, 255, paint->paint_cursor_col[3]);
+
+ immBegin(GL_LINES, 2);
+
if (stroke->constrain_line) {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- stroke->constrained_pos[0], stroke->constrained_pos[1]);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(pos, stroke->constrained_pos[0], stroke->constrained_pos[1]);
}
else {
- sdrawline((int)stroke->last_mouse_position[0], (int)stroke->last_mouse_position[1],
- x, y);
+ immVertex2f(pos, stroke->last_mouse_position[0], stroke->last_mouse_position[1]);
+ immVertex2f(pos, x, y);
}
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immEnd();
+
+ immUnbindProgram();
+
+ setlinestyle(0);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index 31c471c3517..7c3aca80ada 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -59,8 +59,7 @@
#include "RNA_access.h"
#include "RNA_define.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
+#include "GPU_matrix.h"
#include "IMB_colormanagement.h"
#include "IMB_imbuf_types.h"
@@ -130,17 +129,12 @@ bool paint_convert_bb_to_rect(rcti *rect,
* 2D screens-space bounding box into four 3D planes) */
void paint_calc_redraw_planes(float planes[4][4],
const ARegion *ar,
- RegionView3D *rv3d,
Object *ob,
const rcti *screen_rect)
{
BoundBox bb;
- bglMats mats;
rcti rect;
- memset(&bb, 0, sizeof(BoundBox));
- view3d_get_transformation(ar, rv3d, ob, &mats);
-
/* use some extra space just in case */
rect = *screen_rect;
rect.xmin -= 2;
@@ -148,7 +142,7 @@ void paint_calc_redraw_planes(float planes[4][4],
rect.ymin -= 2;
rect.ymax += 2;
- ED_view3d_clipping_calc(&bb, planes, &mats, &rect);
+ ED_view3d_clipping_calc(&bb, planes, ar, ob, &rect);
negate_m4(planes);
}
@@ -290,8 +284,8 @@ static void imapaint_pick_uv(Scene *scene, Object *ob, unsigned int faceindex, c
/* get the needed opengl matrices */
glGetIntegerv(GL_VIEWPORT, view);
- glGetFloatv(GL_MODELVIEW_MATRIX, (float *)matrix);
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
+ gpuGetModelViewMatrix3D(matrix);
+ gpuGetProjectionMatrix3D(proj);
view[0] = view[1] = 0;
mul_m4_m4m4(matrix, matrix, ob->obmat);
mul_m4_m4m4(matrix, proj, matrix);
@@ -447,7 +441,8 @@ void paint_sample_color(bContext *C, ARegion *ar, int x, int y, bool texpaint_pr
if (CTX_wm_view3d(C) && texpaint_proj) {
/* first try getting a colour directly from the mesh faces if possible */
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
bool sample_success = false;
ImagePaintSettings *imapaint = &scene->toolsettings->imapaint;
bool use_material = (imapaint->mode == IMAGEPAINT_MODE_MATERIAL);
@@ -561,8 +556,9 @@ static int brush_curve_preset_exec(bContext *C, wmOperator *op)
if (br) {
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape"));
- BKE_paint_invalidate_cursor_overlay(scene, br->curve);
+ BKE_paint_invalidate_cursor_overlay(scene, sl, br->curve);
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 84e98181dfb..d1965d93172 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -626,8 +626,7 @@ static bool sculpt_get_redraw_rect(ARegion *ar, RegionView3D *rv3d,
return 1;
}
-void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
- RegionView3D *rv3d, Object *ob)
+void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
{
PBVH *pbvh = ob->sculpt->pbvh;
/* copy here, original will be used below */
@@ -635,7 +634,7 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar,
sculpt_extend_redraw_rect_previous(ob, &rect);
- paint_calc_redraw_planes(planes, ar, rv3d, ob, &rect);
+ paint_calc_redraw_planes(planes, ar, ob, &rect);
/* we will draw this rect, so now we can set it as the previous partial rect.
* Note that we don't update with the union of previous/current (rect), only with
@@ -2044,6 +2043,10 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
mul_v3_v3(offset, ss->cache->scale);
mul_v3_fl(offset, bstrength);
+ /* XXX - this shouldn't be necessary, but sculpting crashes in blender2.8 otherwise
+ * initialize before threads so they can do curve mapping */
+ curvemapping_initialize(brush->curve);
+
/* threaded loop over nodes */
SculptThreadedTaskData data = {
.sd = sd, .ob = ob, .brush = brush, .nodes = nodes,
@@ -5361,8 +5364,12 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op)
if (mmd)
multires_force_update(ob);
- if (flush_recalc || (ob->sculpt && ob->sculpt->bm))
+ /* Always for now, so leaving sculpt mode always ensures scene is in
+ * a consistent state.
+ */
+ if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) {
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ }
if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) {
/* Dynamic topology must be disabled before exiting sculpt
diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c
index fd2a0b15cb9..d7a4ea9c950 100644
--- a/source/blender/editors/sculpt_paint/sculpt_uv.c
+++ b/source/blender/editors/sculpt_paint/sculpt_uv.c
@@ -55,6 +55,8 @@
#include "ED_image.h"
#include "ED_mesh.h"
+#include "GPU_immediate.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -64,7 +66,6 @@
#include "paint_intern.h"
#include "uvedit_intern.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "UI_view2d.h"
@@ -212,18 +213,17 @@ static void brush_drawcursor_uvsculpt(bContext *C, int x, int y, void *UNUSED(cu
alpha *= (size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN);
}
- glPushMatrix();
-
- glTranslatef((float)x, (float)y, 0.0f);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3fvAlpha(brush->add_col, alpha);
- glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
- glutil_draw_lined_arc(0, (float)(M_PI * 2.0), size, 40);
+ imm_draw_lined_circle(pos, (float)x, (float)y, size, 40);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- glPopMatrix();
+ immUnbindProgram();
}
#undef PX_SIZE_FADE_MAX
#undef PX_SIZE_FADE_MIN
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index f2707b9399f..4c65207d9a0 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -204,8 +204,8 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* first backdrop strips */
y = (float)(-ACHANNEL_HEIGHT(ac));
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c
index 8c278c0b3ae..5ff1d758563 100644
--- a/source/blender/editors/space_api/spacetypes.c
+++ b/source/blender/editors/space_api/spacetypes.c
@@ -96,7 +96,6 @@ void ED_spacetypes_init(void)
ED_spacetype_console();
ED_spacetype_userpref();
ED_spacetype_clip();
- ED_spacetype_collections();
// ...
/* register operator types for screen and all spaces */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index f53d98a1b59..f6e0d7100e9 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -181,8 +181,8 @@ static int buttons_context_path_object(ButsContextPath *path)
/* if we have a scene, use the scene's active object */
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
- TODO_LAYER_CONTEXT; /* use context, not active one */
- SceneLayer *sl = BKE_scene_layer_active(scene);
+
+ SceneLayer *sl = BKE_scene_layer_context_active(scene);
ob = (sl->basact) ? sl->basact->object : NULL;
if (ob) {
@@ -370,7 +370,7 @@ static int buttons_context_path_particle(ButsContextPath *path)
return 0;
}
-static int buttons_context_path_brush(ButsContextPath *path)
+static int buttons_context_path_brush(const bContext *C, ButsContextPath *path)
{
Scene *scene;
Brush *br = NULL;
@@ -384,8 +384,10 @@ static int buttons_context_path_brush(ButsContextPath *path)
else if (buttons_context_path_scene(path)) {
scene = path->ptr[path->len - 1].data;
- if (scene)
- br = BKE_paint_brush(BKE_paint_get_active(scene));
+ if (scene) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ br = BKE_paint_brush(BKE_paint_get_active(scene, sl));
+ }
if (br) {
RNA_id_pointer_create((ID *)br, &path->ptr[path->len]);
@@ -399,7 +401,7 @@ static int buttons_context_path_brush(ButsContextPath *path)
return 0;
}
-static int buttons_context_path_texture(ButsContextPath *path, ButsContextTexture *ct)
+static int buttons_context_path_texture(const bContext *C, ButsContextPath *path, ButsContextTexture *ct)
{
if (ct) {
/* new shading system */
@@ -417,7 +419,7 @@ static int buttons_context_path_texture(ButsContextPath *path, ButsContextTextur
if (id) {
if (GS(id->name) == ID_BR)
- buttons_context_path_brush(path);
+ buttons_context_path_brush(C, path);
else if (GS(id->name) == ID_MA)
buttons_context_path_material(path, false, true);
else if (GS(id->name) == ID_WO)
@@ -571,6 +573,14 @@ static int buttons_context_path_collection(const bContext *C, ButsContextPath *p
if (sc) {
RNA_pointer_create(NULL, &RNA_LayerCollection, sc, &path->ptr[path->len]);
path->len++;
+
+ /* temporary object in context path to get edit mode */
+ Object *ob = CTX_data_active_object(C);
+ if (ob) {
+ RNA_id_pointer_create(&ob->id, &path->ptr[path->len]);
+ path->len++;
+ }
+
return 1;
}
@@ -642,7 +652,7 @@ static int buttons_context_path(const bContext *C, ButsContextPath *path, int ma
found = buttons_context_path_material(path, false, (sbuts->texuser != NULL));
break;
case BCONTEXT_TEXTURE:
- found = buttons_context_path_texture(path, sbuts->texuser);
+ found = buttons_context_path_texture(C, path, sbuts->texuser);
break;
case BCONTEXT_BONE:
found = buttons_context_path_bone(path);
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 872e62dbc97..14d2ca21b0a 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -216,7 +216,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
format = immVertexFormat();
pos_id = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
unsigned int size_id = add_attrib(format, "size", COMP_F32, 1, KEEP_FLOAT);
- unsigned int color_id = add_attrib(format, "color", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
+ unsigned int color_id = add_attrib(format, "color", COMP_F32, 4, KEEP_FLOAT);
unsigned int outline_color_id = add_attrib(format, "outlineColor", COMP_U8, 4, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
@@ -225,7 +225,7 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
/* all same size with black outline */
immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
- immAttrib3ub(outline_color_id, 0, 0, 0);
+ immAttrib4ub(outline_color_id, 0, 0, 0, 255);
y = (float) CHANNEL_FIRST; /* start again at the top */
for (channel = dopesheet->channels.first; channel; channel = channel->next) {
diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c
index 695d04d3850..a76731da9d5 100644
--- a/source/blender/editors/space_clip/clip_draw.c
+++ b/source/blender/editors/space_clip/clip_draw.c
@@ -55,10 +55,10 @@
#include "ED_mask.h"
#include "ED_gpencil.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_types.h"
@@ -66,26 +66,25 @@
#include "UI_resources.h"
#include "UI_view2d.h"
-
#include "BLF_api.h"
#include "clip_intern.h" // own include
/*********************** main area drawing *************************/
-static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width)
+static void draw_keyframe(int frame, int cfra, int sfra, float framelen, int width, unsigned int pos)
{
int height = (frame == cfra) ? 22 : 10;
int x = (frame - sfra) * framelen;
if (width == 1) {
- glBegin(GL_LINES);
- glVertex2i(x, 0);
- glVertex2i(x, height * UI_DPI_FAC);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex2i(pos, x, 0);
+ immVertex2i(pos, x, height * UI_DPI_FAC);
+ immEnd();
}
else {
- glRecti(x, 0, x + width, height * UI_DPI_FAC);
+ immRecti(pos, x, 0, x + width, height * UI_DPI_FAC);
}
}
@@ -166,6 +165,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
BKE_movieclip_get_cache_segments(clip, &sc->user, &totseg, &points);
ED_region_cache_draw_cached_segments(ar, totseg, points, sfra, efra);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* track */
if (act_track || act_plane_track) {
for (i = sfra - clip->start_frame + 1, a = 0; i <= efra - clip->start_frame + 1; i++) {
@@ -189,14 +191,17 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) {
framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a);
- if (framenr != i)
- glColor4ub(128, 128, 0, 96);
- else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a))
- glColor4ub(255, 255, 0, 196);
- else
- glColor4ub(255, 255, 0, 96);
+ if (framenr != i) {
+ immUniformColor4ub(128, 128, 0, 96);
+ }
+ else if (generic_track_is_marker_keyframed(act_track, act_plane_track, a)) {
+ immUniformColor4ub(255, 255, 0, 196);
+ }
+ else {
+ immUniformColor4ub(255, 255, 0, 96);
+ }
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
+ immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 4 * UI_DPI_FAC);
}
}
}
@@ -206,7 +211,7 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
int n = reconstruction->camnr;
MovieReconstructedCamera *cameras = reconstruction->cameras;
- glColor4ub(255, 0, 0, 96);
+ immUniformColor4ub(255, 0, 0, 96);
for (i = sfra, a = 0; i <= efra; i++) {
bool ok = false;
@@ -223,8 +228,9 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
a++;
}
- if (!ok)
- glRecti((i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
+ if (!ok) {
+ immRecti(pos, (i - sfra + clip->start_frame - 1) * framelen, 0, (i - sfra + clip->start_frame) * framelen, 8 * UI_DPI_FAC);
+ }
}
}
@@ -233,15 +239,22 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc
/* current frame */
x = (sc->user.framenr - sfra) / (efra - sfra + 1) * ar->winx;
- UI_ThemeColor(TH_CFRAME);
- glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+
+ immUnbindProgram();
ED_region_cache_draw_curfra_label(sc->user.framenr, x, 8.0f * UI_DPI_FAC);
+ pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* solver keyframes */
- glColor4ub(175, 255, 0, 255);
- draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
- draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2);
+ immUniformColor4ub(175, 255, 0, 255);
+ draw_keyframe(act_object->keyframe1 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+ draw_keyframe(act_object->keyframe2 + clip->start_frame - 1, CFRA, sfra, framelen, 2, pos);
+
+ immUnbindProgram();
/* movie clip animation */
if ((sc->mode == SC_MODE_MASKEDIT) && sc->mask_info.mask) {
@@ -275,11 +288,16 @@ static void draw_movieclip_muted(ARegion *ar, int width, int height, float zoomx
{
int x, y;
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glColor3f(0.0f, 0.0f, 0.0f);
- glRectf(x, y, x + zoomx * width, y + zoomy * height);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immRectf(pos, x, y, x + zoomx * width, y + zoomy * height);
+
+ immUnbindProgram();
}
static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf,
@@ -297,7 +315,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
+ imm_draw_checker_box(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y);
}
/* non-scaled proxy shouldn't use filtering */
@@ -307,13 +325,7 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar,
filter = GL_NEAREST;
}
- /* set zoom */
- glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter);
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
-
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter, zoomx * width / ibuf->x, zoomy * height / ibuf->y);
if (sc->flag & SC_SHOW_METADATA) {
rctf frame;
@@ -335,31 +347,31 @@ static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int
/* draw boundary border for frame if stabilization is enabled */
if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) {
- glColor3f(0.0f, 0.0f, 0.0f);
-
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
+ setlinestyle(3);
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_NOR);
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix3D(sc->stabmat); /* XXX can we make stabmat a 2D matrix? --merwin */
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- glScalef(zoomx, zoomy, 1.0f);
- glMultMatrixf(sc->stabmat);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
- glBegin(GL_LINE_LOOP);
- glVertex2f(0.0f, 0.0f);
- glVertex2f(width, 0.0f);
- glVertex2f(width, height);
- glVertex2f(0.0f, height);
- glEnd();
+ imm_draw_line_box(pos, 0.0f, 0.0f, width, height);
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
glDisable(GL_COLOR_LOGIC_OP);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+
+ setlinestyle(0);
}
}
@@ -423,69 +435,113 @@ static void draw_track_path(SpaceClip *sc, MovieClip *UNUSED(clip), MovieTrackin
i++;
}
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (!tiny) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
if (TRACK_VIEW_SELECTED(sc, track)) {
- glPointSize(5.0f);
- glBegin(GL_POINTS);
- for (i = a; i < b; i++) {
- if (i != curindex)
- glVertex2f(path[i][0], path[i][1]);
+ if ((b - a - 1) >= 1) {
+ glPointSize(5.0f);
+
+ immBegin(GL_POINTS, b - a - 1);
+
+ for (i = a; i < b; i++) {
+ if (i != curindex) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+ }
+
+ immEnd();
}
- glEnd();
}
- glLineWidth(3.0f);
- glBegin(GL_LINE_STRIP);
- for (i = a; i < b; i++)
- glVertex2f(path[i][0], path[i][1]);
- glEnd();
- }
+ if ((b - a) >= 2) {
+ glLineWidth(3.0f);
- UI_ThemeColor(TH_PATH_BEFORE);
+ immBegin(GL_LINE_STRIP, b - a);
+
+ for (i = a; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
+ }
+ }
if (TRACK_VIEW_SELECTED(sc, track)) {
glPointSize(3.0f);
- glBegin(GL_POINTS);
- for (i = a; i < b; i++) {
- if (i == count + 1)
- UI_ThemeColor(TH_PATH_AFTER);
- if (i != curindex)
- glVertex2f(path[i][0], path[i][1]);
+ if ((curindex - a) >= 1) {
+ immUniformThemeColor(TH_PATH_BEFORE);
+
+ immBegin(GL_POINTS, curindex - a);
+
+ for (i = a; i < curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
}
- glEnd();
- }
- UI_ThemeColor(TH_PATH_BEFORE);
+ if ((b - curindex - 1) >= 1) {
+ immUniformThemeColor(TH_PATH_AFTER);
+
+ immBegin(GL_POINTS, b - curindex - 1);
+
+ for (i = curindex + 1; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
+ }
+ }
glLineWidth(1);
- glBegin(GL_LINE_STRIP);
- for (i = a; i < b; i++) {
- if (i == count + 1)
- UI_ThemeColor(TH_PATH_AFTER);
+ if ((curindex - a + 1) >= 2) {
+ immUniformThemeColor(TH_PATH_BEFORE);
+
+ immBegin(GL_LINE_STRIP, curindex - a + 1);
+
+ for (i = a; i <= curindex; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
+
+ immEnd();
+ }
+
+ if ((b - curindex) >= 2) {
+ immUniformThemeColor(TH_PATH_AFTER);
+
+ immBegin(GL_LINE_STRIP, b - curindex);
+
+ for (i = curindex; i < b; i++) {
+ immVertex2f(pos, path[i][0], path[i][1]);
+ }
- glVertex2f(path[i][0], path[i][1]);
+ immEnd();
}
- glEnd();
+
+ immUnbindProgram();
}
static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height)
+ const float marker_pos[2], int width, int height, unsigned int position)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
bool show_search = false;
float px[2];
- UI_ThemeColor(TH_MARKER_OUTLINE);
-
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
glLineWidth(tiny ? 1.0f : 3.0f);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+
if ((marker->flag & MARKER_DISABLED) == 0) {
float pos[2];
float p[2];
@@ -500,51 +556,54 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT
marker->pattern_corners[2], marker->pattern_corners[3]))
{
glPointSize(tiny ? 3.0f : 4.0f);
- glBegin(GL_POINTS);
- glVertex2f(pos[0], pos[1]);
- glEnd();
+
+ immBegin(GL_POINTS, 1);
+ immVertex2f(position, pos[0], pos[1]);
+ immEnd();
}
else {
- glBegin(GL_LINES);
- glVertex2f(pos[0] + px[0] * 2, pos[1]);
- glVertex2f(pos[0] + px[0] * 8, pos[1]);
+ immBegin(GL_LINES, 8);
+
+ immVertex2f(position, pos[0] + px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] + px[0] * 8, pos[1]);
- glVertex2f(pos[0] - px[0] * 2, pos[1]);
- glVertex2f(pos[0] - px[0] * 8, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 2, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 8, pos[1]);
- glVertex2f(pos[0], pos[1] - px[1] * 2);
- glVertex2f(pos[0], pos[1] - px[1] * 8);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 8);
- glVertex2f(pos[0], pos[1] + px[1] * 2);
- glVertex2f(pos[0], pos[1] + px[1] * 8);
- glEnd();
+ immVertex2f(position, pos[0], pos[1] + px[1] * 2);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 8);
+
+ immEnd();
}
}
/* pattern and search outline */
- glPushMatrix();
- glTranslate2fv(marker_pos);
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
if (sc->flag & SC_SHOW_MARKER_PATTERN) {
- glBegin(GL_LINE_LOOP);
- glVertex2fv(marker->pattern_corners[0]);
- glVertex2fv(marker->pattern_corners[1]);
- glVertex2fv(marker->pattern_corners[2]);
- glVertex2fv(marker->pattern_corners[3]);
- glEnd();
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2fv(position, marker->pattern_corners[0]);
+ immVertex2fv(position, marker->pattern_corners[1]);
+ immVertex2fv(position, marker->pattern_corners[2]);
+ immVertex2fv(position, marker->pattern_corners[3]);
+ immEnd();
}
show_search = (TRACK_VIEW_SELECTED(sc, track) &&
((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
+
if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) {
- glBegin(GL_LINE_LOOP);
- glVertex2f(marker->search_min[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_max[1]);
- glVertex2f(marker->search_min[0], marker->search_max[1]);
- glEnd();
- }
- glPopMatrix();
+ imm_draw_line_box(position, marker->search_min[0],
+ marker->search_min[1],
+ marker->search_max[0],
+ marker->search_max[1]);
+ }
+
+ gpuPopMatrix();
}
static void track_colors(MovieTrackingTrack *track, int act, float col[3], float scol[3])
@@ -568,7 +627,7 @@ static void track_colors(MovieTrackingTrack *track, int act, float col[3], float
}
static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int width, int height, int act, int sel)
+ const float marker_pos[2], int width, int height, int act, int sel, unsigned int position)
{
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
bool show_search = false;
@@ -586,18 +645,18 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
float pos[2], p[2];
if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else
- UI_ThemeColor(TH_LOCK_MARKER);
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
+ }
+ else {
+ immUniformThemeColor(TH_LOCK_MARKER);
+ }
}
else {
- if (track->flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->flag & SELECT) ? scol : col);
}
add_v2_v2v2(pos, marker->pos, track->offset);
@@ -609,123 +668,104 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
marker->pattern_corners[2], marker->pattern_corners[3]))
{
glPointSize(tiny ? 1.0f : 2.0f);
- glBegin(GL_POINTS);
- glVertex2f(pos[0], pos[1]);
- glEnd();
+
+ immBegin(GL_POINTS, 1);
+ immVertex2f(position, pos[0], pos[1]);
+ immEnd();
}
else {
- glBegin(GL_LINES);
- glVertex2f(pos[0] + px[0] * 3, pos[1]);
- glVertex2f(pos[0] + px[0] * 7, pos[1]);
+ immBegin(GL_LINES, 8);
+
+ immVertex2f(position, pos[0] + px[0] * 3, pos[1]);
+ immVertex2f(position, pos[0] + px[0] * 7, pos[1]);
- glVertex2f(pos[0] - px[0] * 3, pos[1]);
- glVertex2f(pos[0] - px[0] * 7, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 3, pos[1]);
+ immVertex2f(position, pos[0] - px[0] * 7, pos[1]);
- glVertex2f(pos[0], pos[1] - px[1] * 3);
- glVertex2f(pos[0], pos[1] - px[1] * 7);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 3);
+ immVertex2f(position, pos[0], pos[1] - px[1] * 7);
- glVertex2f(pos[0], pos[1] + px[1] * 3);
- glVertex2f(pos[0], pos[1] + px[1] * 7);
- glEnd();
+ immVertex2f(position, pos[0], pos[1] + px[1] * 3);
+ immVertex2f(position, pos[0], pos[1] + px[1] * 7);
+
+ immEnd();
+
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ setlinestyle(3);
- glColor3f(0.0f, 0.0f, 0.0f);
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_NOR);
- glBegin(GL_LINES);
- glVertex2fv(pos);
- glVertex2fv(marker_pos);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex2fv(position, pos);
+ immVertex2fv(position, marker_pos);
+ immEnd();
glDisable(GL_COLOR_LOGIC_OP);
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+
+ setlinestyle(0);
}
}
/* pattern */
- glPushMatrix();
- glTranslate2fv(marker_pos);
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
if (tiny) {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
- }
- else {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
+ setlinestyle(3);
}
- if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
- if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->pat_flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else UI_ThemeColor(TH_LOCK_MARKER);
+ if (track->flag & TRACK_LOCKED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
+ }
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_LOCK_MARKER, 64);
+ }
+ else {
+ immUniformThemeColor(TH_LOCK_MARKER);
+ }
+ }
+ else if (marker->flag & MARKER_DISABLED) {
+ if (act) {
+ immUniformThemeColor(TH_ACT_MARKER);
}
- else if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->pat_flag & SELECT)
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
- else UI_ThemeColor(TH_DIS_MARKER);
+ else if (track->pat_flag & SELECT) {
+ immUniformThemeColorShade(TH_DIS_MARKER, 128);
}
else {
- if (track->pat_flag & SELECT)
- glColor3fv(scol);
- else glColor3fv(col);
+ immUniformThemeColor(TH_DIS_MARKER);
}
+ }
+ else {
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
+ }
- glBegin(GL_LINE_LOOP);
- glVertex2fv(marker->pattern_corners[0]);
- glVertex2fv(marker->pattern_corners[1]);
- glVertex2fv(marker->pattern_corners[2]);
- glVertex2fv(marker->pattern_corners[3]);
- glEnd();
+ if ((track->pat_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_PATTERN)) {
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2fv(position, marker->pattern_corners[0]);
+ immVertex2fv(position, marker->pattern_corners[1]);
+ immVertex2fv(position, marker->pattern_corners[2]);
+ immVertex2fv(position, marker->pattern_corners[3]);
+ immEnd();
}
/* search */
show_search = (TRACK_VIEW_SELECTED(sc, track) &&
((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0;
- if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
- if (track->flag & TRACK_LOCKED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->search_flag & SELECT)
- UI_ThemeColorShade(TH_LOCK_MARKER, 64);
- else UI_ThemeColor(TH_LOCK_MARKER);
- }
- else if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else if (track->search_flag & SELECT)
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
- else UI_ThemeColor(TH_DIS_MARKER);
- }
- else {
- if (track->search_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
- }
- glBegin(GL_LINE_LOOP);
- glVertex2f(marker->search_min[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_min[1]);
- glVertex2f(marker->search_max[0], marker->search_max[1]);
- glVertex2f(marker->search_min[0], marker->search_max[1]);
- glEnd();
+ if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) {
+ imm_draw_line_box(position, marker->search_min[0],
+ marker->search_min[1],
+ marker->search_max[0],
+ marker->search_max[1]);
}
if (tiny) {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- }
- else {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ setlinestyle(0);
}
- glPopMatrix();
+ gpuPopMatrix();
}
static float get_shortest_pattern_side(MovieTrackingMarker *marker)
@@ -746,7 +786,7 @@ static float get_shortest_pattern_side(MovieTrackingMarker *marker)
return sqrtf(len_sq);
}
-static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2])
+static void draw_marker_slide_square(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
float tdx, tdy;
@@ -758,15 +798,10 @@ static void draw_marker_slide_square(float x, float y, float dx, float dy, int o
tdy += px[1];
}
- glBegin(GL_QUADS);
- glVertex3f(x - tdx, y + tdy, 0.0f);
- glVertex3f(x + tdx, y + tdy, 0.0f);
- glVertex3f(x + tdx, y - tdy, 0.0f);
- glVertex3f(x - tdx, y - tdy, 0.0f);
- glEnd();
+ immRectf(pos, x - tdx, y - tdy, x + tdx, y + tdy);
}
-static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2])
+static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int outline, float px[2], unsigned int pos)
{
float tdx, tdy;
@@ -778,15 +813,16 @@ static void draw_marker_slide_triangle(float x, float y, float dx, float dy, int
tdy += px[1];
}
- glBegin(GL_TRIANGLES);
- glVertex3f(x, y, 0.0f);
- glVertex3f(x - tdx, y, 0.0f);
- glVertex3f(x, y + tdy, 0.0f);
- glEnd();
+ immBegin(GL_TRIANGLES, 3);
+ immVertex2f(pos, x, y);
+ immVertex2f(pos, x - tdx, y);
+ immVertex2f(pos, x, y + tdy);
+ immEnd();
}
static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
- const float marker_pos[2], int outline, int sel, int act, int width, int height)
+ const float marker_pos[2], int outline, int sel, int act,
+ int width, int height, unsigned int pos)
{
float dx, dy, patdx, patdy, searchdx, searchdy;
int tiny = sc->flag & SC_SHOW_TINY_MARKER;
@@ -801,11 +837,11 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
track_colors(track, act, col, scol);
if (outline) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
+ immUniformThemeColor(TH_MARKER_OUTLINE);
}
- glPushMatrix();
- glTranslate2fv(marker_pos);
+ gpuPushMatrix();
+ gpuTranslate2fv(marker_pos);
dx = 6.0f / width / sc->zoom;
dy = 6.0f / height / sc->zoom;
@@ -822,17 +858,14 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
if ((sc->flag & SC_SHOW_MARKER_SEARCH) && ((track->search_flag & SELECT) == sel || outline)) {
if (!outline) {
- if (track->search_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->search_flag & SELECT) ? scol : col);
}
/* search offset square */
- draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px);
+ draw_marker_slide_square(marker->search_min[0], marker->search_max[1], searchdx, searchdy, outline, px, pos);
/* search re-sizing triangle */
- draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px);
+ draw_marker_slide_triangle(marker->search_max[0], marker->search_min[1], searchdx, searchdy, outline, px, pos);
}
if ((sc->flag & SC_SHOW_MARKER_PATTERN) && ((track->pat_flag & SELECT) == sel || outline)) {
@@ -842,16 +875,13 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
float tilt_ctrl[2];
if (!outline) {
- if (track->pat_flag & SELECT)
- glColor3fv(scol);
- else
- glColor3fv(col);
+ immUniformColor3fv((track->pat_flag & SELECT) ? scol : col);
}
/* pattern's corners sliding squares */
for (i = 0; i < 4; i++) {
draw_marker_slide_square(marker->pattern_corners[i][0], marker->pattern_corners[i][1],
- patdx / 1.5f, patdy / 1.5f, outline, px);
+ patdx / 1.5f, patdy / 1.5f, outline, px, pos);
}
/* ** sliders to control overall pattern ** */
@@ -861,18 +891,16 @@ static void draw_marker_slide_zones(SpaceClip *sc, MovieTrackingTrack *track, Mo
glLineWidth(outline ? 3.0f : 1.0f);
- glBegin(GL_LINES);
- glVertex2f(0.0f, 0.0f);
- glVertex2fv(tilt_ctrl);
- glEnd();
-
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, 0.0f, 0.0f);
+ immVertex2fv(pos, tilt_ctrl);
+ immEnd();
/* slider to control pattern tilt */
- draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px);
+ draw_marker_slide_square(tilt_ctrl[0], tilt_ctrl[1], patdx, patdy, outline, px, pos);
}
- glPopMatrix();
+ gpuPopMatrix();
}
static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTrackingMarker *marker,
@@ -890,16 +918,17 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra
fontsize = BLF_height_max(fontid);
if (marker->flag & MARKER_DISABLED) {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else
- UI_ThemeColorShade(TH_DIS_MARKER, 128);
+ if (act) {
+ UI_FontThemeColor(fontid, TH_ACT_MARKER);
+ }
+ else {
+ unsigned char color[4];
+ UI_GetThemeColorShade4ubv(TH_DIS_MARKER, 128, color);
+ BLF_color4ubv(fontid, color);
+ }
}
else {
- if (act)
- UI_ThemeColor(TH_ACT_MARKER);
- else
- UI_ThemeColor(TH_SEL_MARKER);
+ UI_FontThemeColor(fontid, act ? TH_ACT_MARKER : TH_SEL_MARKER);
}
if ((sc->flag & SC_SHOW_MARKER_SEARCH) &&
@@ -960,10 +989,7 @@ static void plane_track_colors(bool is_active, float color[3], float selected_co
{
UI_GetThemeColor3fv(TH_MARKER, color);
- if (is_active)
- UI_GetThemeColor3fv(TH_ACT_MARKER, selected_color);
- else
- UI_GetThemeColor3fv(TH_SEL_MARKER, selected_color);
+ UI_GetThemeColor3fv(is_active ? TH_ACT_MARKER : TH_SEL_MARKER, selected_color);
}
static void getArrowEndPoint(const int width, const int height, const float zoom,
@@ -1052,7 +1078,7 @@ static void draw_plane_marker_image(Scene *scene,
plane_marker->corners,
perspective_matrix);
- homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix);
+ homogeneous_2d_to_gl_matrix(perspective_matrix, gl_matrix); /* XXX update for new 2D matrix API --merwin */
if (plane_track->image_opacity != 1.0f || ibuf->planes == 32) {
transparent = true;
@@ -1060,9 +1086,6 @@ static void draw_plane_marker_image(Scene *scene,
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- glColor4f(1.0, 1.0, 1.0, plane_track->image_opacity);
-
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1073,20 +1096,38 @@ static void draw_plane_marker_image(Scene *scene,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, GL_RGBA,
GL_UNSIGNED_BYTE, display_buffer);
- glPushMatrix();
- glMultMatrixf(gl_matrix);
+ gpuPushMatrix();
+ gpuMultMatrix3D(gl_matrix); /* XXX update for new 2D matrix API --merwin */
+
+ VertexFormat *imm_format = immVertexFormat();
+ unsigned int pos = add_attrib(imm_format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texCoord = add_attrib(imm_format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniform4f("color", 1.0f, 1.0f, 1.0f, plane_track->image_opacity);
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GL_QUADS, 4);
+
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, 0.0f, 0.0f);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, 1.0f, 0.0f);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, 1.0f);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, 0.0f, 1.0f);
+
+ immEnd();
- glBegin(GL_QUADS);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, 1.0f);
- glEnd();
+ immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
if (transparent) {
glDisable(GL_BLEND);
@@ -1109,20 +1150,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
BKE_image_has_ibuf(plane_track->image, NULL);
const bool draw_plane_quad = !has_image || plane_track->image_opacity == 0.0f;
float px[2];
-
- if (draw_outline) {
- UI_ThemeColor(TH_MARKER_OUTLINE);
- }
- else {
- float color[3], selected_color[3];
- plane_track_colors(is_active_track, color, selected_color);
- if (is_selected_track) {
- glColor3fv(selected_color);
- }
- else {
- glColor3fv(color);
- }
- }
+ float color[3], selected_color[3];
px[0] = 1.0f / width / sc->zoom;
px[1] = 1.0f / height / sc->zoom;
@@ -1132,66 +1160,85 @@ static void draw_plane_marker_ex(SpaceClip *sc, Scene *scene, MovieTrackingPlane
draw_plane_marker_image(scene, plane_track, plane_marker);
}
- if (draw_plane_quad) {
+ if (draw_plane_quad || is_selected_track) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- const bool stipple = !draw_outline && tiny;
- const bool thick = draw_outline && !tiny;
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- if (stipple) {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- GPU_basic_shader_line_stipple(3, 0xAAAA);
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
}
else {
- GPU_basic_shader_bind_enable(GPU_SHADER_LINE);
+ plane_track_colors(is_active_track, color, selected_color);
+
+ immUniformColor3fv(is_selected_track ? selected_color : color);
}
- GPU_basic_shader_line_width(thick ? 3.0f : 1.0f);
+ if (draw_plane_quad) {
+ const bool stipple = !draw_outline && tiny;
+ const bool thick = draw_outline && !tiny;
- /* Draw rectangle itself. */
- glBegin(GL_LINE_LOOP);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(plane_marker->corners[1]);
- glVertex2fv(plane_marker->corners[2]);
- glVertex2fv(plane_marker->corners[3]);
- glEnd();
+ if (stipple) {
+ setlinestyle(3);
+ }
- /* Draw axis. */
- if (!draw_outline) {
- float end_point[2];
- glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
+ glLineWidth(thick ? 3.0f : 1.0f);
- glBegin(GL_LINES);
+ /* Draw rectangle itself. */
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2fv(pos, plane_marker->corners[0]);
+ immVertex2fv(pos, plane_marker->corners[1]);
+ immVertex2fv(pos, plane_marker->corners[2]);
+ immVertex2fv(pos, plane_marker->corners[3]);
+ immEnd();
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
- glColor3f(1.0, 0.0, 0.0f);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
+ /* Draw axis. */
+ if (!draw_outline) {
+ float end_point[2];
- getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
- glColor3f(0.0, 1.0, 0.0f);
- glVertex2fv(plane_marker->corners[0]);
- glVertex2fv(end_point);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
- glEnd();
+ immBegin(GL_LINES, 2);
- glPopAttrib();
- }
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[1], end_point);
+ immVertex2fv(pos, plane_marker->corners[0]);
+ immVertex2fv(pos, end_point);
- if (stipple) {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- }
- else {
- GPU_basic_shader_bind_disable(GPU_SHADER_LINE);
+ immEnd();
+
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+
+ immBegin(GL_LINES, 2);
+
+ getArrowEndPoint(width, height, sc->zoom, plane_marker->corners[0], plane_marker->corners[3], end_point);
+ immVertex2fv(pos, plane_marker->corners[0]);
+ immVertex2fv(pos, end_point);
+
+ immEnd();
+ }
+
+ if (stipple) {
+ setlinestyle(0);
+ }
}
- }
- /* Draw sliders. */
- if (is_selected_track) {
- int i;
- for (i = 0; i < 4; i++) {
- draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
- 3.0f * px[0], 3.0f * px[1], draw_outline, px);
+ /* Draw sliders. */
+ if (is_selected_track) {
+ if (draw_outline) {
+ immUniformThemeColor(TH_MARKER_OUTLINE);
+ }
+ else {
+ immUniformColor3fv(selected_color);
+ }
+
+ int i;
+ for (i = 0; i < 4; i++) {
+ draw_marker_slide_square(plane_marker->corners[i][0], plane_marker->corners[i][1],
+ 3.0f * px[0], 3.0f * px[1], draw_outline, px, pos);
+ }
}
+
+ immUnbindProgram();
}
}
@@ -1243,13 +1290,13 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
- glPushMatrix();
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix3D(sc->stabmat); /* XXX would like 2D stabmat --merwin */
+ gpuScale2f(width, height);
act_track = BKE_tracking_track_get_active(tracking);
@@ -1315,6 +1362,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
+ unsigned int position = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* markers outline and non-selected areas */
track = tracksbase->first;
fp = marker_pos;
@@ -1325,10 +1376,10 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (MARKER_VISIBLE(sc, track, marker)) {
copy_v2_v2(cur_pos, fp ? fp : marker->pos);
- draw_marker_outline(sc, track, marker, cur_pos, width, height);
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height);
+ draw_marker_outline(sc, track, marker, cur_pos, width, height, position);
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 0, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 1, 0, 0, width, height, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 0, 0, width, height, position);
if (fp)
fp += 2;
@@ -1351,8 +1402,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (!act) {
copy_v2_v2(cur_pos, fp ? fp : marker->pos);
- draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1);
- draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height);
+ draw_marker_areas(sc, track, marker, cur_pos, width, height, 0, 1, position);
+ draw_marker_slide_zones(sc, track, marker, cur_pos, 0, 1, 0, width, height, position);
}
if (fp)
@@ -1371,8 +1422,8 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
if (MARKER_VISIBLE(sc, act_track, marker)) {
copy_v2_v2(cur_pos, active_pos ? active_pos : marker->pos);
- draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1);
- draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height);
+ draw_marker_areas(sc, act_track, marker, cur_pos, width, height, 1, 1, position);
+ draw_marker_slide_zones(sc, act_track, marker, cur_pos, 0, 1, 1, width, height, position);
}
}
}
@@ -1381,7 +1432,6 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
float pos[4], vec[4], mat[4][4], aspy;
- glEnable(GL_POINT_SMOOTH);
glPointSize(3.0f);
aspy = 1.0f / clip->tracking.camera.pixel_aspect;
@@ -1410,28 +1460,34 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
sub_v2_v2(vec, npos);
- if (len_squared_v2(vec) < (3.0f * 3.0f))
- glColor3f(0.0f, 1.0f, 0.0f);
- else
- glColor3f(1.0f, 0.0f, 0.0f);
+ if (len_squared_v2(vec) < (3.0f * 3.0f)) {
+ immUniformColor3f(0.0f, 1.0f, 0.0f);
+ }
+ else {
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
+ }
- glBegin(GL_POINTS);
- if (undistort)
- glVertex3f(pos[0] / width, pos[1] / (height * aspy), 0);
- else
- glVertex3f(npos[0] / width, npos[1] / (height * aspy), 0);
- glEnd();
+ immBegin(GL_POINTS, 1);
+
+ if (undistort) {
+ immVertex2f(position, pos[0] / width, pos[1] / (height * aspy));
+ }
+ else {
+ immVertex2f(position, npos[0] / width, npos[1] / (height * aspy));
+ }
+
+ immEnd();
}
}
}
track = track->next;
}
-
- glDisable(GL_POINT_SMOOTH);
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
if (sc->flag & SC_SHOW_NAMES) {
/* scaling should be cleared before drawing texts, otherwise font would also be scaled */
@@ -1457,7 +1513,7 @@ static void draw_tracking_tracks(SpaceClip *sc, Scene *scene, ARegion *ar, Movie
}
}
- glPopMatrix();
+ gpuPopMatrix();
if (marker_pos)
MEM_freeN(marker_pos);
@@ -1484,11 +1540,15 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
UI_view2d_view_to_region_fl(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix3D(sc->stabmat); /* XXX make 2D */
+ gpuScale2f(width, height);
+
+ unsigned int position = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* grid */
if (sc->flag & SC_SHOW_GRID) {
@@ -1560,22 +1620,26 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
pos[1] += dy;
}
- glColor3f(1.0f, 0.0f, 0.0f);
+ immUniformColor3f(1.0f, 0.0f, 0.0f);
for (i = 0; i <= n; i++) {
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, n + 1);
+
for (j = 0; j <= n; j++) {
- glVertex2fv(grid[i][j]);
+ immVertex2fv(position, grid[i][j]);
}
- glEnd();
+
+ immEnd();
}
for (j = 0; j <= n; j++) {
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, n + 1);
+
for (i = 0; i <= n; i++) {
- glVertex2fv(grid[i][j]);
+ immVertex2fv(position, grid[i][j]);
}
- glEnd();
+
+ immEnd();
}
}
@@ -1594,7 +1658,8 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
continue;
}
- glColor4fv(layer->color);
+ immUniformColor4fv(layer->color);
+
glLineWidth(layer->thickness);
glPointSize((float)(layer->thickness + 2));
@@ -1604,7 +1669,6 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
while (stroke) {
if (stroke->flag & GP_STROKE_2DSPACE) {
if (stroke->totpoints > 1) {
- glBegin(GL_LINE_STRIP);
for (i = 0; i < stroke->totpoints - 1; i++) {
float npos[2], dpos[2], len;
int steps;
@@ -1627,19 +1691,22 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
sub_v2_v2v2(dpos, npos, pos);
mul_v2_fl(dpos, 1.0f / steps);
+ immBegin(GL_LINE_STRIP, steps + 1);
+
for (j = 0; j <= steps; j++) {
BKE_tracking_distort_v2(tracking, pos, tpos);
- glVertex2f(tpos[0] / width, tpos[1] / (height * aspy));
+ immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy));
add_v2_v2(pos, dpos);
}
+
+ immEnd();
}
- glEnd();
}
else if (stroke->totpoints == 1) {
- glBegin(GL_POINTS);
- glVertex2f(stroke->points[0].x + offsx, stroke->points[0].y + offsy);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex2f(position, stroke->points[0].x + offsx, stroke->points[0].y + offsy);
+ immEnd();
}
}
@@ -1653,7 +1720,9 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip,
}
}
- glPopMatrix();
+ immUnbindProgram();
+
+ gpuPopMatrix();
}
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
@@ -1750,8 +1819,8 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
* associated with the clip is already drawn in draw_distortion
*/
if ((sc->flag & SC_MANUAL_CALIBRATION) == 0 || is_track_source) {
- glPushMatrix();
- glMultMatrixf(sc->unistabmat);
+ gpuPushMatrix();
+ gpuMultMatrix3D(sc->unistabmat); /* XXX make 2D */
if (is_track_source) {
MovieTrackingTrack *track = BKE_tracking_track_get_active(&sc->clip->tracking);
@@ -1760,13 +1829,13 @@ void clip_draw_grease_pencil(bContext *C, int onlyv2d)
int framenr = ED_space_clip_get_clip_frame_number(sc);
MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr);
- glTranslate2fv(marker->pos);
+ gpuTranslate2fv(marker->pos);
}
}
ED_gpencil_draw_2dimage(C);
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c
index b373358b49c..a9d02018f49 100644
--- a/source/blender/editors/space_clip/clip_graph_draw.c
+++ b/source/blender/editors/space_clip/clip_graph_draw.c
@@ -72,7 +72,7 @@ static void tracking_segment_point_cb(void *userdata, MovieTrackingTrack *UNUSED
immVertex2f(data->pos, scene_framenr, val);
}
-static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord)
+static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
{
TrackMotionCurveUserData *data = (TrackMotionCurveUserData *) userdata;
float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
@@ -90,8 +90,13 @@ static void tracking_segment_start_cb(void *userdata, MovieTrackingTrack *track,
immUniformColor4fv(col);
- /* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GL_LINE_STRIP, track->markersnr);
+ if (is_point) {
+ immBeginAtMost(GL_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GL_LINE_STRIP, track->markersnr);
+ }
}
static void tracking_segment_end_cb(void *UNUSED(userdata), int UNUSED(coord))
@@ -114,14 +119,13 @@ static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track,
if (sel == data->sel) {
immUniformThemeColor(sel ? TH_HANDLE_VERTEX_SELECT : TH_HANDLE_VERTEX);
- glPushMatrix();
- glTranslatef(scene_framenr, val, 0.0f);
- glScalef(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize, 1.0f);
- gpuMatrixUpdate_legacy();
+ gpuPushMatrix();
+ gpuTranslate2f(scene_framenr, val);
+ gpuScale2f(1.0f / data->xscale * data->hsize, 1.0f / data->yscale * data->hsize);
imm_draw_lined_circle(data->pos, 0, 0, 0.7, 8);
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -148,9 +152,6 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int p
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&userdata, tracking_segment_knot_cb, NULL, NULL);
-
- gpuMatrixUpdate_legacy();
-
/* draw graph lines */
glEnable(GL_BLEND);
clip_graph_tracking_values_iterate(sc,
@@ -166,8 +167,6 @@ static void draw_tracks_motion_curves(View2D *v2d, SpaceClip *sc, unsigned int p
(sc->flag & SC_SHOW_GRAPH_SEL_ONLY) != 0,
(sc->flag & SC_SHOW_GRAPH_HIDDEN) != 0,
&userdata, tracking_segment_knot_cb, NULL, NULL);
-
- gpuMatrixUpdate_legacy();
}
typedef struct TrackErrorCurveUserData {
@@ -220,7 +219,7 @@ static void tracking_error_segment_point_cb(void *userdata,
}
}
-static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord)
+static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *track, int coord, bool is_point)
{
if (coord == 1) {
TrackErrorCurveUserData *data = (TrackErrorCurveUserData *) userdata;
@@ -237,8 +236,13 @@ static void tracking_error_segment_start_cb(void *userdata, MovieTrackingTrack *
immUniformColor4fv(col);
- /* Graph can be composed of smaller segments, if any marker is disabled */
- immBeginAtMost(GL_LINE_STRIP, track->markersnr);
+ if (is_point) { /* This probably never happens here, but just in case... */
+ immBeginAtMost(GL_POINTS, 1);
+ }
+ else {
+ /* Graph can be composed of smaller segments, if any marker is disabled */
+ immBeginAtMost(GL_LINE_STRIP, track->markersnr);
+ }
}
}
@@ -323,11 +327,12 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
UI_view2d_grid_draw(v2d, grid, V2D_GRIDLINES_ALL);
UI_view2d_grid_free(grid);
- unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ if (clip) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ glPointSize(3.0f);
- if (clip) {
if (sc->flag & SC_SHOW_GRAPH_TRACKS_MOTION) {
draw_tracks_motion_curves(v2d, sc, pos);
}
@@ -339,9 +344,9 @@ void clip_draw_graph(SpaceClip *sc, ARegion *ar, Scene *scene)
if (sc->flag & SC_SHOW_GRAPH_FRAMES) {
draw_frame_curves(sc, pos);
}
- }
- immUnbindProgram();
+ immUnbindProgram();
+ }
/* frame range */
clip_draw_sfra_efra(v2d, scene);
diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h
index 14393c6968b..ffc7a41f0aa 100644
--- a/source/blender/editors/space_clip/clip_intern.h
+++ b/source/blender/editors/space_clip/clip_intern.h
@@ -125,12 +125,12 @@ void ED_clip_tool_props_register(struct ARegionType *art);
/* clip_utils.c */
void clip_graph_tracking_values_iterate_track(struct SpaceClip *sc, struct MovieTrackingTrack *track, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_values_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, struct MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord));
void clip_graph_tracking_iterate(struct SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c
index 6026036c05d..1cddacc0fc6 100644
--- a/source/blender/editors/space_clip/clip_utils.c
+++ b/source/blender/editors/space_clip/clip_utils.c
@@ -44,6 +44,7 @@
#include "BKE_depsgraph.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -61,7 +62,7 @@ void clip_graph_tracking_values_iterate_track(
SpaceClip *sc, MovieTrackingTrack *track, void *userdata,
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord,
int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -90,8 +91,14 @@ void clip_graph_tracking_values_iterate_track(
}
if (!open) {
- if (segment_start)
- segment_start(userdata, track, coord);
+ if (segment_start) {
+ if ((i + 1) == track->markersnr) {
+ segment_start(userdata, track, coord, true);
+ }
+ else {
+ segment_start(userdata, track, coord, (track->markers[i + 1].flag & MARKER_DISABLED));
+ }
+ }
open = true;
prevval = marker->pos[coord];
@@ -122,7 +129,7 @@ void clip_graph_tracking_values_iterate(
SpaceClip *sc, bool selected_only, bool include_hidden, void *userdata,
void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker,
int coord, int scene_framenr, float val),
- void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord),
+ void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord, bool is_point),
void (*segment_end)(void *userdata, int coord))
{
MovieClip *clip = ED_space_clip_get_clip(sc);
@@ -257,13 +264,13 @@ void clip_draw_cfra(SpaceClip *sc, ARegion *ar, Scene *scene)
/* because the frame number text is subject to the same scaling as the contents of the view */
float xscale, yscale;
UI_view2d_scale_get(v2d, &xscale, &yscale);
- glPushMatrix();
- glScalef(1.0f / xscale, 1.0f, 1.0f);
+ gpuPushMatrix();
+ gpuScale2f(1.0f / xscale, 1.0f);
ED_region_cache_draw_curfra_label(sc->user.framenr, (float)sc->user.framenr * xscale, 18);
/* restore view transform */
- glPopMatrix();
+ gpuPopMatrix();
}
void clip_draw_sfra_efra(View2D *v2d, Scene *scene)
diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c
index 05e69968e35..9f35fff5e78 100644
--- a/source/blender/editors/space_clip/space_clip.c
+++ b/source/blender/editors/space_clip/space_clip.c
@@ -60,7 +60,7 @@
#include "IMB_imbuf.h"
-#include "BIF_gl.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -1213,13 +1213,13 @@ static void clip_main_region_draw(const bContext *C, ARegion *ar)
show_cursor |= sc->around == V3D_AROUND_CURSOR;
if (show_cursor) {
- glPushMatrix();
- glTranslatef(x, y, 0);
- glScalef(zoomx, zoomy, 0);
- glMultMatrixf(sc->stabmat);
- glScalef(width, height, 0);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
+ gpuMultMatrix3D(sc->stabmat); /* XXX make this a 2D matrix */
+ gpuScale2f(width, height);
ED_image_draw_cursor(ar, sc->cursor);
- glPopMatrix();
+ gpuPopMatrix();
}
clip_draw_cache_and_notes(C, sc, ar);
diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c
index d28cbe5fb1d..169eb76399b 100644
--- a/source/blender/editors/space_clip/tracking_ops.c
+++ b/source/blender/editors/space_clip/tracking_ops.c
@@ -1534,7 +1534,8 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
update_stabilization = true;
if ((act_track->flag & TRACK_USE_2D_STAB) == 0) {
act_track->flag |= TRACK_USE_2D_STAB;
- } else {
+ }
+ else {
stab->tot_track--;
}
BLI_assert(0 <= stab->tot_track);
@@ -1543,7 +1544,8 @@ static int join_tracks_exec(bContext *C, wmOperator *op)
update_stabilization = true;
if ((act_track->flag & TRACK_USE_2D_STAB_ROT) == 0) {
act_track->flag |= TRACK_USE_2D_STAB_ROT;
- } else {
+ }
+ else {
stab->tot_rot_track--;
}
BLI_assert(0 <= stab->tot_rot_track);
diff --git a/source/blender/editors/space_clip/tracking_ops_orient.c b/source/blender/editors/space_clip/tracking_ops_orient.c
index 12b97504dc7..7b44e9317ba 100644
--- a/source/blender/editors/space_clip/tracking_ops_orient.c
+++ b/source/blender/editors/space_clip/tracking_ops_orient.c
@@ -70,7 +70,6 @@ static Object *get_camera_with_movieclip(Scene *scene, MovieClip *clip)
return camera;
}
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
if (ob->type == OB_CAMERA) {
diff --git a/source/blender/editors/space_collections/CMakeLists.txt b/source/blender/editors/space_collections/CMakeLists.txt
deleted file mode 100644
index 1cc4a40d657..00000000000
--- a/source/blender/editors/space_collections/CMakeLists.txt
+++ /dev/null
@@ -1,45 +0,0 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# Contributor(s): Jacques Beaurain.
-#
-# ***** END GPL LICENSE BLOCK *****
-
-set(INC
- ../include
- ../../blenkernel
- ../../blenlib
- ../../blentranslation
- ../../gpu
- ../../makesdna
- ../../makesrna
- ../../windowmanager
- ../../../../intern/guardedalloc
- ../../../../intern/glew-mx
-)
-
-set(INC_SYS
- ${GLEW_INCLUDE_PATH}
-)
-
-set(SRC
- collections_ops.c
- space_collections.c
-
- collections_intern.h
-)
-
-blender_add_lib(bf_editor_space_collections "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/space_collections/collections_ops.c b/source/blender/editors/space_collections/collections_ops.c
deleted file mode 100644
index 7e1bf8091b0..00000000000
--- a/source/blender/editors/space_collections/collections_ops.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_collections/collections_ops.c
- * \ingroup spcollections
- */
-
-#include "BKE_context.h"
-#include "BKE_layer.h"
-#include "BKE_report.h"
-
-#include "ED_screen.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_access.h"
-#include "RNA_define.h"
-
-#include "collections_intern.h" /* own include */
-
-/* -------------------------------------------------------------------- */
-/* polls */
-
-static SceneCollection *collection_manager_collection_active(bContext *C)
-{
- TODO_LAYER_OPERATORS;
- /* consider that we may have overrides active
- * leading to no active collections */
- return CTX_data_scene_collection(C);
-}
-
-static int operator_not_master_collection_active(bContext *C)
-{
- SceneCollection *sc = collection_manager_collection_active(C);
- if (sc == NULL) {
- return 1;
- }
-
- return (sc == BKE_collection_master(CTX_data_scene(C))) ? 0 : 1;
-}
-
-static int operator_top_collection_active(bContext *C)
-{
- SceneCollection *sc = collection_manager_collection_active(C);
- if (sc == NULL) {
- return 0;
- }
-
- TODO_LAYER_OPERATORS;
- /* see if it's a top collection */
- return 1;
-}
-
-static int operator_collection_active(bContext *C)
-{
- return collection_manager_collection_active(C) ? 1 : 0;
-}
-
-/* -------------------------------------------------------------------- */
-/* collection manager operators */
-
-static int collection_link_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_link not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_collection_link(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Collection";
- ot->idname = "COLLECTIONS_OT_collection_link";
- ot->description = "Link a new collection to the active layer";
-
- /* api callbacks */
- ot->invoke = collection_link_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int collection_unlink_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_collection_unlink not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_collection_unlink(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Collection";
- ot->idname = "COLLECTIONS_OT_collection_unlink";
- ot->description = "Link a new collection to the active layer";
-
- /* api callbacks */
- ot->invoke = collection_unlink_invoke;
- ot->poll = operator_top_collection_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Scene *scene = CTX_data_scene(C);
- SceneLayer *sl = CTX_data_scene_layer(C);
-
- SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
- BKE_collection_link(sl, sc);
-
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-static void COLLECTIONS_OT_collection_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Collection";
- ot->idname = "COLLECTIONS_OT_collection_new";
- ot->description = "Add a new collection to the scene, and link it to the active layer";
-
- /* api callbacks */
- ot->exec = collection_new_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- TODO_LAYER_OVERRIDE;
- BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_override_new not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_override_new(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "New Override";
- ot->idname = "COLLECTIONS_OT_override_new";
- ot->description = "Add a new override to the active collection";
-
- /* api callbacks */
- ot->invoke = override_new_invoke;
- ot->poll = operator_collection_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int delete_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_OT_delete not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_delete(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Delete";
- ot->idname = "COLLECTIONS_OT_delete";
- ot->description = "Delete active override or collection";
-
- /* api callbacks */
- ot->invoke = delete_invoke;
- ot->poll = operator_not_master_collection_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int select_exec(bContext *C, wmOperator *op)
-{
- SceneLayer *sl = CTX_data_scene_layer(C);
- const int collection_index = RNA_int_get(op->ptr, "collection_index");
- sl->active_collection = collection_index;
- WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OPERATOR_FINISHED;
-}
-
-static void COLLECTIONS_OT_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select";
- ot->idname = "COLLECTIONS_OT_select";
- ot->description = "Change active collection or override";
-
- /* api callbacks */
- ot->exec = select_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-
- RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
- "Index of collection to select", 0, INT_MAX);
-}
-
-static int rename_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "COLLECTIONS_rename not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_rename(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Rename";
- ot->idname = "COLLECTIONS_OT_rename";
- ot->description = "Rename active collection or override";
-
- /* api callbacks */
- ot->invoke = rename_invoke;
- ot->poll = operator_not_master_collection_active;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* -------------------------------------------------------------------- */
-/* property editor operators */
-
-static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
-{
- TODO_LAYER_OPERATORS;
- BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet");
- return OPERATOR_CANCELLED;
-}
-
-static void COLLECTIONS_OT_objects_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Objects";
- ot->idname = "COLLECTIONS_OT_objects_add";
- ot->description = "Add selected objects to collection";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static void COLLECTIONS_OT_objects_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Object";
- ot->idname = "COLLECTIONS_OT_objects_remove";
- ot->description = "Remove object from collection";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static void COLLECTIONS_OT_objects_select(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Select Objects";
- ot->idname = "COLLECTIONS_OT_objects_select";
- ot->description = "Selected collection objects";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static void COLLECTIONS_OT_objects_deselect(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Deselect Objects";
- ot->idname = "COLLECTIONS_OT_objects_deselect";
- ot->description = "Deselected collection objects";
-
- /* api callbacks */
- ot->invoke = stubs_invoke;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/* ************************** registration - operator types **********************************/
-
-void collections_operatortypes(void)
-{
- WM_operatortype_append(COLLECTIONS_OT_delete);
- WM_operatortype_append(COLLECTIONS_OT_select);
- WM_operatortype_append(COLLECTIONS_OT_rename);
- WM_operatortype_append(COLLECTIONS_OT_collection_link);
- WM_operatortype_append(COLLECTIONS_OT_collection_unlink);
- WM_operatortype_append(COLLECTIONS_OT_collection_new);
- WM_operatortype_append(COLLECTIONS_OT_override_new);
-
- WM_operatortype_append(COLLECTIONS_OT_objects_add);
- WM_operatortype_append(COLLECTIONS_OT_objects_remove);
- WM_operatortype_append(COLLECTIONS_OT_objects_select);
- WM_operatortype_append(COLLECTIONS_OT_objects_deselect);
-}
-
-void collections_keymap(wmKeyConfig *keyconf)
-{
- wmKeyMap *keymap = WM_keymap_find(keyconf, "Collections Manager", SPACE_COLLECTIONS, 0);
-
- /* selection */
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
-
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
-
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_collection_new", NKEY, KM_PRESS, KM_CTRL, 0);
-
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "COLLECTIONS_OT_delete", DELKEY, KM_PRESS, 0, 0);
-}
diff --git a/source/blender/editors/space_collections/space_collections.c b/source/blender/editors/space_collections/space_collections.c
deleted file mode 100644
index 7dd50e5cbac..00000000000
--- a/source/blender/editors/space_collections/space_collections.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/editors/space_collections/space_collections.c
- * \ingroup spcollections
- */
-
-#include <string.h>
-
-#include "MEM_guardedalloc.h"
-
-#include "BIF_gl.h"
-
-#include "BKE_context.h"
-#include "BKE_screen.h"
-
-#include "BLI_ghash.h"
-#include "BLI_listbase.h"
-
-#include "ED_screen.h"
-#include "ED_space_api.h"
-
-#include "UI_resources.h"
-#include "UI_view2d.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "collections_intern.h" /* own include */
-
-/* ******************** default callbacks for collection manager space ***************** */
-
-static SpaceLink *collections_new(const bContext *UNUSED(C))
-{
- ARegion *ar;
- SpaceCollections *scollection; /* hmm, that's actually a good band name... */
-
- scollection = MEM_callocN(sizeof(SpaceCollections), __func__);
- scollection->spacetype = SPACE_COLLECTIONS;
-
- /* header */
- ar = MEM_callocN(sizeof(ARegion), "header for collection manager");
- BLI_addtail(&scollection->regionbase, ar);
- ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
-
- /* main region */
- ar = MEM_callocN(sizeof(ARegion), "main region for collection manager");
- BLI_addtail(&scollection->regionbase, ar);
- ar->regiontype = RGN_TYPE_WINDOW;
- ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM | V2D_SCROLL_HORIZONTAL_HIDE | V2D_SCROLL_VERTICAL_HIDE);
- ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
-
- return (SpaceLink *)scollection;
-}
-
-static void collections_free(SpaceLink *UNUSED(sl))
-{
-}
-
-static SpaceLink *collections_duplicate(SpaceLink *sl)
-{
- SpaceCollections *scollection = MEM_dupallocN(sl);
-
- /* clear or remove stuff from old */
-
- return (SpaceLink *)scollection;
-}
-
-/* add handlers, stuff you only do once or on area/region changes */
-static void collection_main_region_init(wmWindowManager *wm, ARegion *ar)
-{
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
- ar->v2d.scroll |= (V2D_SCROLL_VERTICAL_FULLR | V2D_SCROLL_HORIZONTAL_FULLR);
-
- /* own keymap */
- wmKeyMap *keymap = WM_keymap_find(wm->defaultconf, "Layer Manager", SPACE_COLLECTIONS, 0);
- WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
-}
-
-static void collections_main_region_draw(const bContext *C, ARegion *ar)
-{
- SpaceCollections *spc = CTX_wm_space_collections(C);
- View2D *v2d = &ar->v2d;
-
- if (spc->flag & SC_COLLECTION_DATA_REFRESH) {
- }
-
- /* v2d has initialized flag, so this call will only set the mask correct */
- UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
-
- UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
-
- /* reset view matrix */
- UI_view2d_view_restore(C);
-
- /* scrollers */
- View2DScrollers *scrollers;
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
- UI_view2d_scrollers_draw(C, v2d, scrollers);
- UI_view2d_scrollers_free(scrollers);
-}
-
-/* add handlers, stuff you only do once or on area/region changes */
-static void collections_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar)
-{
- ED_region_header_init(ar);
-}
-
-static void collections_header_region_draw(const bContext *C, ARegion *ar)
-{
- ED_region_header(C, ar);
-}
-
-static void collections_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
-{
- switch (wmn->category) {
- case NC_SCENE:
- if (wmn->data == ND_LAYER) {
- ED_region_tag_redraw(ar);
- }
- break;
- case NC_SPACE:
- if (wmn->data == ND_SPACE_COLLECTIONS) {
- ED_region_tag_redraw(ar);
- }
- }
-}
-
-/* only called once, from space/spacetypes.c */
-void ED_spacetype_collections(void)
-{
- SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype collections");
- ARegionType *art;
-
- st->spaceid = SPACE_COLLECTIONS;
- strncpy(st->name, "LayerManager", BKE_ST_MAXNAME);
-
- st->new = collections_new;
- st->free = collections_free;
- st->duplicate = collections_duplicate;
- st->operatortypes = collections_operatortypes;
- st->keymap = collections_keymap;
-
- /* regions: main window */
- art = MEM_callocN(sizeof(ARegionType), "spacetype collections region");
- art->regionid = RGN_TYPE_WINDOW;
- art->init = collection_main_region_init;
- art->draw = collections_main_region_draw;
- art->listener = collections_main_region_listener;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
- BLI_addhead(&st->regiontypes, art);
-
- /* regions: header */
- art = MEM_callocN(sizeof(ARegionType), "spacetype collections header");
- art->regionid = RGN_TYPE_HEADER;
- art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
- art->init = collections_header_region_init;
- art->draw = collections_header_region_draw;
- BLI_addhead(&st->regiontypes, art);
-
- BKE_spacetype_register(st);
-}
diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c
index c45b8acae0a..8055e262611 100644
--- a/source/blender/editors/space_console/console_draw.c
+++ b/source/blender/editors/space_console/console_draw.c
@@ -158,8 +158,8 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha
int offl = 0, offc = 0;
int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN};
int pen[2];
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
xy[1] += tvc->lheight / 6;
console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL);
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 06066372828..a1bd1f25427 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -42,7 +42,6 @@
# include "BLI_winstuff.h"
#endif
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "BKE_context.h"
@@ -71,8 +70,6 @@
#include "WM_api.h"
#include "WM_types.h"
-//#include "GPU_draw.h"
-//#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
#include "filelist.h"
@@ -341,6 +338,7 @@ static void file_draw_preview(
float scale;
int ex, ey;
bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
BLI_assert(imb != NULL);
@@ -387,12 +385,12 @@ static void file_draw_preview(
/* the image */
if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
- UI_ThemeColor(TH_TEXT);
+ UI_GetThemeColor4fv(TH_TEXT, col);
}
- else {
- glColor4f(1.0, 1.0, 1.0, 1.0);
- }
- glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale);
+
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect,
+ scale, scale, 1.0f, 1.0f, col);
if (icon) {
UI_icon_draw_aspect((float)xco, (float)yco, icon, icon_aspect, 1.0f);
@@ -400,8 +398,8 @@ static void file_draw_preview(
/* border */
if (use_dropshadow) {
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2,KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2,KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
@@ -462,15 +460,18 @@ static void draw_background(FileLayout *layout, View2D *v2d)
int i;
int sy;
- UI_ThemeColorShade(TH_BACK, -7);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -7);
/* alternating flat shade background */
for (i = 0; (i <= layout->rows); i += 2) {
sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) - layout->tile_border_y;
- glRectf(v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
-
+ immRectf(pos, v2d->cur.xmin, (float)sy, v2d->cur.xmax, (float)(sy + layout->tile_h + 2 * layout->tile_border_y));
}
+
+ immUnbindProgram();
}
static void draw_dividers(FileLayout *layout, View2D *v2d)
@@ -481,9 +482,9 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
unsigned int vertex_ct = 0;
unsigned char col_hi[3], col_lo[3];
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
- unsigned color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
vertex_ct = (v2d->cur.xmax - v2d->tot.xmin) / step + 1; /* paint at least 1 divider */
vertex_ct *= 4; /* vertex_count = 2 points per divider * 2 lines per divider */
@@ -609,9 +610,6 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLI_join_dirfile(path, sizeof(path), root, file->relpath);
- UI_ThemeColor4(TH_TEXT);
-
-
if (!(file_selflag & FILE_SEL_EDITING)) {
if ((params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ||
(file_selflag & FILE_SEL_SELECTED))
diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c
index 631ff06a77a..71d49e0dc2e 100644
--- a/source/blender/editors/space_file/fsmenu.c
+++ b/source/blender/editors/space_file/fsmenu.c
@@ -169,12 +169,15 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *path)
static void fsmenu_entry_generate_name(struct FSMenuEntry *fsentry, char *name, size_t name_size)
{
- char temp[FILE_MAX];
+ int offset = 0;
+ int len = name_size;
- BLI_strncpy(temp, fsentry->path, FILE_MAX);
- BLI_add_slash(temp);
- BLI_getlastdir(temp, name, name_size);
- BLI_del_slash(name);
+ if (BLI_path_name_at_index(fsentry->path, -1, &offset, &len)) {
+ /* use as size */
+ len += 1;
+ }
+
+ BLI_strncpy(name, &fsentry->path[offset], MIN2(len, name_size));
if (!name[0]) {
name[0] = '/';
name[1] = '\0';
@@ -537,28 +540,22 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks)
/* Finally get user favorite places */
if (read_bookmarks) {
UInt32 seed;
- OSErr err = noErr;
- CFArrayRef pathesArray;
- LSSharedFileListRef list;
- LSSharedFileListItemRef itemRef;
- CFIndex i, pathesCount;
- CFURLRef cfURL = NULL;
- CFStringRef pathString = NULL;
- list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
- pathesArray = LSSharedFileListCopySnapshot(list, &seed);
- pathesCount = CFArrayGetCount(pathesArray);
+ LSSharedFileListRef list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
+ CFArrayRef pathesArray = LSSharedFileListCopySnapshot(list, &seed);
+ CFIndex pathesCount = CFArrayGetCount(pathesArray);
- for (i = 0; i < pathesCount; i++) {
- itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
+ for (CFIndex i = 0; i < pathesCount; i++) {
+ LSSharedFileListItemRef itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
- err = LSSharedFileListItemResolve(itemRef,
- kLSSharedFileListNoUserInteraction |
- kLSSharedFileListDoNotMountVolumes,
- &cfURL, NULL);
- if (err != noErr)
+ CFURLRef cfURL = NULL;
+ OSErr err = LSSharedFileListItemResolve(itemRef,
+ kLSSharedFileListNoUserInteraction |
+ kLSSharedFileListDoNotMountVolumes,
+ &cfURL, NULL);
+ if (err != noErr || !cfURL)
continue;
- pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
+ CFStringRef pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
continue;
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index 516814b63b4..cbb8e98e7e0 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -616,30 +616,31 @@ static void graph_panel_driverVar__rotDiff(uiLayout *layout, ID *id, DriverVar *
Object *ob2 = (Object *)dtar2->id;
PointerRNA dtar_ptr, dtar2_ptr;
uiLayout *col;
-
+
/* initialize RNA pointer to the target */
- RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
- RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
-
- /* Bone 1 */
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
+ RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
+
+ /* Object 1 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Bone 1"), ICON_NONE);
-
+ uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
+
if (dtar->id && GS(dtar->id->name) == ID_OB && ob1->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar->id, &RNA_Pose, ob1->pose, &tar_ptr);
uiItemPointerR(col, &dtar_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
-
+
+ /* Object 2 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
- uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Bone 2"), ICON_NONE);
-
+ uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
+
if (dtar2->id && GS(dtar2->id->name) == ID_OB && ob2->pose) {
PointerRNA tar_ptr;
-
+
RNA_pointer_create(dtar2->id, &RNA_Pose, ob2->pose, &tar_ptr);
uiItemPointerR(col, &dtar2_ptr, "bone_target", &tar_ptr, "bones", "", ICON_BONE_DATA);
}
@@ -658,8 +659,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
/* initialize RNA pointer to the target */
RNA_pointer_create(id, &RNA_DriverTarget, dtar, &dtar_ptr);
RNA_pointer_create(id, &RNA_DriverTarget, dtar2, &dtar2_ptr);
-
- /* Bone 1 */
+
+ /* Object 1 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar_ptr, "id", 0, IFACE_("Object 1"), ICON_NONE);
@@ -673,7 +674,8 @@ static void graph_panel_driverVar__locDiff(uiLayout *layout, ID *id, DriverVar *
uiLayoutSetRedAlert(col, false); /* we can clear it again now - it's only needed when creating the ID/Bone fields */
uiItemR(col, &dtar_ptr, "transform_space", 0, NULL, ICON_NONE);
-
+
+ /* Object 2 */
col = uiLayoutColumn(layout, true);
uiLayoutSetRedAlert(col, (dtar2->flag & DTAR_FLAG_INVALID)); /* XXX: per field... */
uiItemR(col, &dtar2_ptr, "id", 0, IFACE_("Object 2"), ICON_NONE);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index 9781c909ef6..e382c2dbd29 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -46,12 +46,11 @@
#include "BKE_curve.h"
#include "BKE_fcurve.h"
-
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_anim_api.h"
@@ -85,38 +84,46 @@ static void draw_fcurve_modifier_controls_envelope(FModifier *fcm, View2D *v2d)
FCM_EnvelopeData *fed;
const float fac = 0.05f * BLI_rctf_size_x(&v2d->cur);
int i;
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw two black lines showing the standard reference levels */
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
glLineWidth(1);
setlinestyle(5);
- glBegin(GL_LINES);
- glVertex2f(v2d->cur.xmin, env->midval + env->min);
- glVertex2f(v2d->cur.xmax, env->midval + env->min);
+ immBegin(PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, env->midval + env->min);
+ immVertex2f(pos, v2d->cur.xmax, env->midval + env->min);
- glVertex2f(v2d->cur.xmin, env->midval + env->max);
- glVertex2f(v2d->cur.xmax, env->midval + env->max);
- glEnd();
+ immVertex2f(pos, v2d->cur.xmin, env->midval + env->max);
+ immVertex2f(pos, v2d->cur.xmax, env->midval + env->max);
+ immEnd();
+
setlinestyle(0);
-
+
/* set size of vertices (non-adjustable for now) */
glPointSize(2.0f);
/* for now, point color is fixed, and is white */
- glColor3f(1.0f, 1.0f, 1.0f);
+ immUniformColor3f(1.0f, 1.0f, 1.0f);
- glBegin(GL_POINTS);
+ immBeginAtMost(PRIM_POINTS, env->totvert * 2);
+
for (i = 0, fed = env->data; i < env->totvert; i++, fed++) {
/* only draw if visible
* - min/max here are fixed, not relative
*/
if (IN_RANGE(fed->time, (v2d->cur.xmin - fac), (v2d->cur.xmax + fac))) {
- glVertex2f(fed->time, fed->min);
- glVertex2f(fed->time, fed->max);
+ immVertex2f(pos, fed->time, fed->min);
+ immVertex2f(pos, fed->time, fed->max);
}
}
- glEnd();
+
+ immEnd();
+
+ immUnbindProgram();
}
/* *************************** */
@@ -181,7 +188,7 @@ static void draw_fcurve_selected_keyframe_vertices(FCurve *fcu, View2D *v2d, boo
/* helper func - draw keyframe vertices only for an F-Curve */
static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, unsigned pos)
{
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
@@ -236,7 +243,7 @@ static void draw_fcurve_selected_handle_vertices(FCurve *fcu, View2D *v2d, bool
static void draw_fcurve_handle_vertices(FCurve *fcu, View2D *v2d, bool sel_handle_only, unsigned pos)
{
/* smooth outlines for more consistent appearance */
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
/* set handle size */
immUniform1f("size", (UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE) + 1.0f) * U.pixelsize);
@@ -302,13 +309,10 @@ static bool draw_fcurve_handles_check(SpaceIpo *sipo, FCurve *fcu)
static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
{
int sel, b;
-
- /* a single call to GL_LINES here around these calls should be sufficient to still
- * get separate line segments, but which aren't wrapped with GL_LINE_STRIP every time we
- * want a single line
- */
- glBegin(GL_LINES);
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* slightly hacky, but we want to draw unselected points before selected ones
* so that selected points are clearly visible
*/
@@ -335,18 +339,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
if ((!prevbezt && (bezt->ipo == BEZT_IPO_BEZ)) || (prevbezt && (prevbezt->ipo == BEZT_IPO_BEZ))) {
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
/* only draw second handle if this segment is bezier */
if (bezt->ipo == BEZT_IPO_BEZ) {
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp + 3); glVertex2fv(fp + 6);
+ immUniformColor4ubv(col);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, fp + 3);
+ immVertex2fv(pos, fp + 6);
+ immEnd();
}
}
else {
@@ -357,9 +367,12 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[0];
UI_GetThemeColor3ubv(basecol + bezt->h1, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
/* only draw second handle if this segment is bezier, and selection is ok */
@@ -369,15 +382,18 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
fp = bezt->vec[1];
UI_GetThemeColor3ubv(basecol + bezt->h2, col);
col[3] = fcurve_display_alpha(fcu) * 255;
- glColor4ubv((GLubyte *)col);
-
- glVertex2fv(fp); glVertex2fv(fp + 3);
+ immUniformColor4ubv(col);
+
+ immBegin(PRIM_LINES, 2);
+ immVertex2fv(pos, fp);
+ immVertex2fv(pos, fp + 3);
+ immEnd();
}
}
}
}
-
- glEnd(); /* GL_LINES */
+
+ immUnbindProgram();
}
/* Samples ---------------- */
@@ -386,36 +402,24 @@ static void draw_fcurve_handles(SpaceIpo *sipo, FCurve *fcu)
* NOTE: the caller MUST HAVE GL_LINE_SMOOTH & GL_BLEND ENABLED, otherwise, the controls don't
* have a consistent appearance (due to off-pixel alignments)...
*/
-static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize)
+static void draw_fcurve_sample_control(float x, float y, float xscale, float yscale, float hsize, unsigned int pos)
{
- static GLuint displist = 0;
-
- /* initialize X shape */
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glBegin(GL_LINES);
- glVertex2f(-0.7f, -0.7f);
- glVertex2f(+0.7f, +0.7f);
-
- glVertex2f(-0.7f, +0.7f);
- glVertex2f(+0.7f, -0.7f);
- glEnd(); /* GL_LINES */
-
- glEndList();
- }
-
/* adjust view transform before starting */
- glTranslatef(x, y, 0.0f);
- glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
-
- /* draw! */
- glCallList(displist);
-
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(1.0f / xscale * hsize, 1.0f / yscale * hsize);
+
+ /* draw X shape */
+ immBegin(GL_LINES, 4);
+ immVertex2f(pos, -0.7f, -0.7f);
+ immVertex2f(pos, +0.7f, +0.7f);
+
+ immVertex2f(pos, -0.7f, +0.7f);
+ immVertex2f(pos, +0.7f, -0.7f);
+ immEnd();
+
/* restore view transform */
- glScalef(xscale / hsize, yscale / hsize, 1.0);
- glTranslatef(-x, -y, 0.0f);
+ gpuPopMatrix();
}
/* helper func - draw keyframe vertices only for an F-Curve */
@@ -428,10 +432,6 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
hsize = UI_GetThemeValuef(TH_VERTEX_SIZE);
UI_view2d_scale_get(&ar->v2d, &xscale, &yscale);
- /* set vertex color */
- if (fcu->flag & (FCURVE_ACTIVE | FCURVE_SELECTED)) UI_ThemeColor(TH_TEXT_HI);
- else UI_ThemeColor(TH_TEXT);
-
/* get verts */
first = fcu->fpt;
last = (first) ? (first + (fcu->totvert - 1)) : (NULL);
@@ -441,10 +441,17 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* anti-aliased lines for more consistent appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
- draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize);
- draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize);
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor((fcu->flag & FCURVE_SELECTED) ? TH_TEXT_HI : TH_TEXT);
+
+ draw_fcurve_sample_control(first->vec[0], first->vec[1], xscale, yscale, hsize, pos);
+ draw_fcurve_sample_control(last->vec[0], last->vec[1], xscale, yscale, hsize, pos);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glDisable(GL_LINE_SMOOTH);
}
@@ -453,7 +460,7 @@ static void draw_fcurve_samples(SpaceIpo *sipo, ARegion *ar, FCurve *fcu)
/* Curve ---------------- */
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
-static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
+static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid, unsigned int pos)
{
SpaceIpo *sipo = (SpaceIpo *)ac->sl;
ChannelDriver *driver;
@@ -523,37 +530,50 @@ static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d
* - apply the unit correction factor to the calculated values so that
* the displayed values appear correctly in the viewport
*/
- glBegin(GL_LINE_STRIP);
-
+
n = (etime - stime) / samplefreq + 0.5f;
- for (i = 0; i <= n; i++) {
- float ctime = stime + i * samplefreq;
- glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
+
+ if (n > 0) {
+ immBegin(PRIM_LINE_STRIP, (n + 1));
+
+ for (i = 0; i <= n; i++) {
+ float ctime = stime + i * samplefreq;
+ immVertex2f(pos, ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
+ }
+
+ immEnd();
}
-
- glEnd();
-
+
/* restore driver */
fcu->driver = driver;
}
/* helper func - draw a samples-based F-Curve */
-static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
+static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos)
{
FPoint *prevfpt = fcu->fpt;
FPoint *fpt = prevfpt + 1;
float fac, v[2];
- int b = fcu->totvert - 1;
+ int b = fcu->totvert;
float unit_scale, offset;
short mapping_flag = ANIM_get_normalization_flags(ac);
+ int count = fcu->totvert;
+
+ if (prevfpt->vec[0] > v2d->cur.xmin) {
+ count++;
+ }
+
+ if ((prevfpt + b - 1)->vec[0] < v2d->cur.xmax) {
+ count++;
+ }
/* apply unit mapping */
- glPushMatrix();
+ gpuPushMatrix();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
- glBegin(GL_LINE_STRIP);
+ immBegin(PRIM_LINE_STRIP, count);
/* extrapolate to left? - left-side of view comes before first keyframe? */
if (prevfpt->vec[0] > v2d->cur.xmin) {
@@ -571,26 +591,19 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
}
- glVertex2fv(v);
+ immVertex2fv(pos, v);
}
- /* if only one sample, add it now */
- if (fcu->totvert == 1)
- glVertex2fv(prevfpt->vec);
-
/* loop over samples, drawing segments */
/* draw curve between first and last keyframe (if there are enough to do so) */
while (b--) {
/* Linear interpolation: just add one point (which should add a new line segment) */
- glVertex2fv(prevfpt->vec);
+ immVertex2fv(pos, prevfpt->vec);
/* get next pointers */
- prevfpt = fpt;
- fpt++;
-
- /* last point? */
- if (b == 0)
- glVertex2fv(prevfpt->vec);
+ if (b > 0) {
+ prevfpt++;
+ }
}
/* extrapolate to right? (see code for left-extrapolation above too) */
@@ -610,11 +623,12 @@ static void draw_fcurve_curve_samples(bAnimContext *ac, ID *id, FCurve *fcu, Vie
v[1] = prevfpt->vec[1] - fac * (prevfpt->vec[1] - fpt->vec[1]);
}
- glVertex2fv(v);
+ immVertex2fv(pos, v);
}
- glEnd();
- glPopMatrix();
+ immEnd();
+
+ gpuPopMatrix();
}
/* helper func - check if the F-Curve only contains easily drawable segments
@@ -635,7 +649,7 @@ static bool fcurve_can_use_simple_bezt_drawing(FCurve *fcu)
}
/* helper func - draw one repeat of an F-Curve (using Bezier curve approximations) */
-static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d)
+static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, unsigned int pos)
{
BezTriple *prevbezt = fcu->bezt;
BezTriple *bezt = prevbezt + 1;
@@ -648,12 +662,15 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
short mapping_flag = ANIM_get_normalization_flags(ac);
/* apply unit mapping */
- glPushMatrix();
+ gpuPushMatrix();
unit_scale = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
- glBegin(GL_LINE_STRIP);
+ /* For now, this assumes the worst case scenario, where all the keyframes have
+ * bezier interpolation, and are drawn at full res.
+ * This is tricky to optimize, but maybe can be improved at some point... */
+ immBeginAtMost(PRIM_LINE_STRIP, (b * 32 + 3));
/* extrapolate to left? */
if (prevbezt->vec[1][0] > v2d->cur.xmin) {
@@ -678,14 +695,14 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[0][1] - prevbezt->vec[1][1]);
}
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
/* if only one keyframe, add it now */
if (fcu->totvert == 1) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
/* draw curve between first and last keyframe (if there are enough to do so) */
@@ -695,17 +712,17 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
v1[0] = bezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else if (prevbezt->ipo == BEZT_IPO_LIN) {
/* Linear interpolation: just add one point (which should add a new line segment) */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else if (prevbezt->ipo == BEZT_IPO_BEZ) {
/* Bezier-Interpolation: draw curve as series of segments between keyframes
@@ -725,7 +742,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
/* only draw one */
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
else {
/* clamp resolution to max of 32 */
@@ -747,8 +764,9 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
BKE_curve_forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, sizeof(float) * 3);
BKE_curve_forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data + 1, resol, sizeof(float) * 3);
- for (fp = data; resol; resol--, fp += 3)
- glVertex2fv(fp);
+ for (fp = data; resol; resol--, fp += 3) {
+ immVertex2fv(pos, fp);
+ }
}
}
@@ -760,7 +778,7 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
if (b == 0) {
v1[0] = prevbezt->vec[1][0];
v1[1] = prevbezt->vec[1][1];
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
}
@@ -787,11 +805,12 @@ static void draw_fcurve_curve_bezts(bAnimContext *ac, ID *id, FCurve *fcu, View2
v1[1] = prevbezt->vec[1][1] - fac * (prevbezt->vec[2][1] - prevbezt->vec[1][1]);
}
- glVertex2fv(v1);
+ immVertex2fv(pos, v1);
}
- glEnd();
- glPopMatrix();
+ immEnd();
+
+ gpuPopMatrix();
}
/* Debugging -------------------------------- */
@@ -812,7 +831,10 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* for now, only show when debugging driver... */
//if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0)
// return;
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* No curve to modify/visualize the result?
* => We still want to show the 1-1 default...
*/
@@ -820,7 +842,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
float t;
/* draw with thin dotted lines in style of what curve would have been */
- glColor3fv(fcu->color);
+ immUniformColor3fv(fcu->color);
setlinestyle(20);
glLineWidth(2.0f);
@@ -828,15 +850,15 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
/* draw 1-1 line, stretching just past the screen limits
* NOTE: we need to scale the y-values to be valid for the units
*/
- glBegin(GL_LINES);
- {
- t = v2d->cur.xmin;
- glVertex2f(t, (t + offset) * unitfac);
-
- t = v2d->cur.xmax;
- glVertex2f(t, (t + offset) * unitfac);
- }
- glEnd();
+ immBegin(PRIM_LINES, 2);
+
+ t = v2d->cur.xmin;
+ immVertex2f(pos, t, (t + offset) * unitfac);
+
+ t = v2d->cur.xmax;
+ immVertex2f(pos, t, (t + offset) * unitfac);
+
+ immEnd();
/* cleanup line drawing */
setlinestyle(0);
@@ -853,53 +875,55 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu)
float co[2];
/* draw dotted lines leading towards this point from both axes ....... */
- glColor3f(0.9f, 0.9f, 0.9f);
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
setlinestyle(5);
- glBegin(GL_LINES);
- {
- /* x-axis lookup */
- co[0] = x;
-
- if (y >= v2d->cur.ymin) {
- co[1] = v2d->cur.ymin - 1.0f;
- glVertex2fv(co);
-
- co[1] = y;
- glVertex2fv(co);
- }
-
- /* y-axis lookup */
+ immBegin(PRIM_LINES, (y >= v2d->cur.ymin) ? 4 : 2);
+
+ /* x-axis lookup */
+ co[0] = x;
+
+ if (y >= v2d->cur.ymin) {
+ co[1] = v2d->cur.ymin - 1.0f;
+ immVertex2fv(pos, co);
+
co[1] = y;
-
- co[0] = v2d->cur.xmin - 1.0f;
- glVertex2fv(co);
-
- co[0] = x;
- glVertex2fv(co);
+ immVertex2fv(pos, co);
}
- glEnd();
+
+ /* y-axis lookup */
+ co[1] = y;
+
+ co[0] = v2d->cur.xmin - 1.0f;
+ immVertex2fv(pos, co);
+
+ co[0] = x;
+ immVertex2fv(pos, co);
+
+ immEnd();
setlinestyle(0);
/* x marks the spot .................................................... */
/* -> outer frame */
- glColor3f(0.9f, 0.9f, 0.9f);
+ immUniformColor3f(0.9f, 0.9f, 0.9f);
glPointSize(7.0);
- glBegin(GL_POINTS);
- glVertex2f(x, y);
- glEnd();
+ immBegin(PRIM_POINTS, 1);
+ immVertex2f(pos, x, y);
+ immEnd();
/* inner frame */
- glColor3f(0.9f, 0.0f, 0.0f);
+ immUniformColor3f(0.9f, 0.0f, 0.0f);
glPointSize(3.0);
- glBegin(GL_POINTS);
- glVertex2f(x, y);
- glEnd();
+ immBegin(PRIM_POINTS, 1);
+ immVertex2f(pos, x, y);
+ immEnd();
}
}
+
+ immUnbindProgram();
}
/* Public Curve-Drawing API ---------------- */
@@ -918,19 +942,24 @@ void graph_draw_ghost_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
/* anti-aliased lines for less jagged appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* the ghost curves are simply sampled F-Curves stored in sipo->ghostCurves */
for (fcu = sipo->ghostCurves.first; fcu; fcu = fcu->next) {
/* set whatever color the curve has set
* - this is set by the function which creates these
* - draw with a fixed opacity of 2
*/
- glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f);
+ immUniformColor4f(fcu->color[0], fcu->color[1], fcu->color[2], 0.5f);
/* simply draw the stored samples */
- draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d);
+ draw_fcurve_curve_samples(ac, NULL, fcu, &ar->v2d, pos);
}
-
+
+ immUnbindProgram();
+
/* restore settings */
setlinestyle(0);
@@ -962,9 +991,10 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
/* map keyframes for drawing if scaled F-Curve */
- if (adt)
- ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
-
+ if (adt) {
+ ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 0, 0);
+ }
+
/* draw curve:
* - curve line may be result of one or more destructive modifiers or just the raw data,
* so we need to check which method should be used
@@ -973,23 +1003,14 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
*/
/* 1) draw curve line */
+ if (((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) ||
+ (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)))
{
/* set color/drawing style for curve itself */
if (BKE_fcurve_is_protected(fcu)) {
/* protected curves (non editable) are drawn with dotted lines */
setlinestyle(2);
}
- if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
- /* muted curves are drawn in a grayish hue */
- /* XXX should we have some variations? */
- UI_ThemeColorShade(TH_HEADER, 50);
- }
- else {
- /* set whatever color the curve has set
- * - unselected curves draw less opaque to help distinguish the selected ones
- */
- glColor4f(fcu->color[0], fcu->color[1], fcu->color[2], fcurve_display_alpha(fcu));
- }
/* draw active F-Curve thicker than the rest to make it stand out */
if (fcu->flag & FCURVE_ACTIVE) {
@@ -1002,27 +1023,46 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
/* anti-aliased lines for less jagged appearance */
if ((sipo->flag & SIPO_BEAUTYDRAW_OFF) == 0) glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ if (((fcu->grp) && (fcu->grp->flag & AGRP_MUTED)) || (fcu->flag & FCURVE_MUTED)) {
+ /* muted curves are drawn in a grayish hue */
+ /* XXX should we have some variations? */
+ immUniformThemeColorShade(TH_HEADER, 50);
+ }
+ else {
+ /* set whatever color the curve has set
+ * - unselected curves draw less opaque to help distinguish the selected ones
+ */
+ immUniformColor4f(fcu->color[0], fcu->color[1], fcu->color[2], fcurve_display_alpha(fcu));
+ }
+
/* draw F-Curve */
if ((fcu->modifiers.first) || (fcu->flag & FCURVE_INT_VALUES)) {
/* draw a curve affected by modifiers or only allowed to have integer values
* by sampling it at various small-intervals over the visible region
*/
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid);
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, pos);
}
else if (((fcu->bezt) || (fcu->fpt)) && (fcu->totvert)) {
/* just draw curve based on defined data (i.e. no modifiers) */
if (fcu->bezt) {
- if (fcurve_can_use_simple_bezt_drawing(fcu))
- draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d);
- else
- draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid);
+ if (fcurve_can_use_simple_bezt_drawing(fcu)) {
+ draw_fcurve_curve_bezts(ac, ale->id, fcu, &ar->v2d, pos);
+ }
+ else {
+ draw_fcurve_curve(ac, ale->id, fcu, &ar->v2d, grid, pos);
+ }
}
else if (fcu->fpt) {
- draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d);
+ draw_fcurve_curve_samples(ac, ale->id, fcu, &ar->v2d, pos);
}
}
-
+
+ immUnbindProgram();
+
/* restore settings */
setlinestyle(0);
@@ -1034,7 +1074,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
* - if the option to only show controls if the F-Curve is selected is enabled, we must obey this
*/
if (!(sipo->flag & SIPO_SELCUVERTSONLY) || (fcu->flag & FCURVE_SELECTED)) {
- if (fcurve_are_keyframes_usable(fcu) == 0) {
+ if (!fcurve_are_keyframes_usable(fcu) && !(fcu->fpt && fcu->totvert)) {
/* only draw controls if this is the active modifier */
if ((fcu->flag & FCURVE_ACTIVE) && (fcm)) {
switch (fcm->type) {
@@ -1050,9 +1090,9 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, fcu, mapping_flag, &offset);
/* apply unit-scaling to all values via OpenGL */
- glPushMatrix();
- glScalef(1.0f, unit_scale, 1.0f);
- glTranslatef(0.0f, offset, 0.0f);
+ gpuPushMatrix();
+ gpuScale2f(1.0f, unit_scale);
+ gpuTranslate2f(0.0f, offset);
/* set this once and for all - all handles and handle-verts should use the same thickness */
glLineWidth(1.0);
@@ -1074,7 +1114,7 @@ void graph_draw_curves(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar, View2DGrid
draw_fcurve_samples(sipo, ar, fcu);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt
index c60d194b620..0bc09981ba5 100644
--- a/source/blender/editors/space_image/CMakeLists.txt
+++ b/source/blender/editors/space_image/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../imbuf
../../gpu
../../makesdna
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index dd575619c0f..8d55c38f9e4 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -60,9 +60,11 @@
#include "BKE_image.h"
#include "BKE_paint.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "BLF_api.h"
#include "ED_gpencil.h"
@@ -87,7 +89,6 @@ static void draw_render_info(const bContext *C,
float zoomx,
float zoomy)
{
- RenderResult *rr;
Render *re = RE_GetRender(scene->id.name);
RenderData *rd = RE_engine_get_render_data(re);
Scene *stats_scene = ED_render_job_get_scene(C);
@@ -95,7 +96,7 @@ static void draw_render_info(const bContext *C,
stats_scene = CTX_data_scene(C);
}
- rr = BKE_image_acquire_renderresult(stats_scene, ima);
+ RenderResult *rr = BKE_image_acquire_renderresult(stats_scene, ima);
if (rr && rr->text) {
float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f};
@@ -107,39 +108,41 @@ static void draw_render_info(const bContext *C,
if (re) {
int total_tiles;
bool need_free_tiles;
- rcti *tiles;
-
- tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
+ rcti *tiles = RE_engine_get_current_tiles(re, &total_tiles, &need_free_tiles);
if (total_tiles) {
- int i, x, y;
- rcti *tile;
-
/* find window pixel coordinates of origin */
+ int x, y;
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y);
- glPushMatrix();
- glTranslatef(x, y, 0.0f);
- glScalef(zoomx, zoomy, 1.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(x, y);
+ gpuScale2f(zoomx, zoomy);
if (rd->mode & R_BORDER) {
- glTranslatef((int)(-rd->border.xmin * rd->xsch * rd->size / 100.0f),
- (int)(-rd->border.ymin * rd->ysch * rd->size / 100.0f),
- 0.0f);
+ /* TODO: round or floor instead of casting to int */
+ gpuTranslate2f((int)(-rd->border.xmin * rd->xsch * rd->size * 0.01f),
+ (int)(-rd->border.ymin * rd->ysch * rd->size * 0.01f));
}
- UI_ThemeColor(TH_FACE_SELECT);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_FACE_SELECT);
glLineWidth(1.0f);
- for (i = 0, tile = tiles; i < total_tiles; i++, tile++) {
- glaDrawBorderCorners(tile, zoomx, zoomy);
+
+ rcti *tile = tiles;
+ for (int i = 0; i < total_tiles; i++, tile++) {
+ immDrawBorderCorners(pos, tile, zoomx, zoomy);
}
+ immUnbindProgram();
+
if (need_free_tiles) {
MEM_freeN(tiles);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -169,28 +172,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* noisy, high contrast make impossible to read if lower alpha is used. */
- glColor4ub(0, 0, 0, 190);
- glRecti(0.0, 0.0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
+ immUniformColor4ub(0, 0, 0, 190);
+ immRecti(pos, 0, 0, BLI_rcti_size_x(&ar->winrct) + 1, UI_UNIT_Y);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
BLF_size(blf_mono_font, 11 * U.pixelsize, U.dpi);
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), "X:%-4d Y:%-4d |", x, y);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
if (zp) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.4f |", 0.5f + 0.5f * (((float)*zp) / (float)0x7fffffff));
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (zpf) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLI_snprintf(str, sizeof(str), " Z:%-.3f |", *zpf);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
@@ -204,14 +213,14 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
else if (cp != NULL) {
BLI_snprintf(str, sizeof(str), " Val:%-.3f |", cp[0] / 255.0f);
}
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
}
if (channels >= 3) {
- glColor3ubv(red);
+ BLF_color3ubv(blf_mono_font, red);
if (fp)
BLI_snprintf(str, sizeof(str), " R:%-.5f", fp[0]);
else if (cp)
@@ -222,7 +231,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
- glColor3ubv(green);
+ BLF_color3ubv(blf_mono_font, green);
if (fp)
BLI_snprintf(str, sizeof(str), " G:%-.5f", fp[1]);
else if (cp)
@@ -233,7 +242,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
dx += BLF_width(blf_mono_font, str, sizeof(str));
- glColor3ubv(blue);
+ BLF_color3ubv(blf_mono_font, blue);
if (fp)
BLI_snprintf(str, sizeof(str), " B:%-.5f", fp[2]);
else if (cp)
@@ -245,7 +254,7 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
dx += BLF_width(blf_mono_font, str, sizeof(str));
if (channels == 4) {
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
if (fp)
BLI_snprintf(str, sizeof(str), " A:%-.4f", fp[3]);
else if (cp)
@@ -267,9 +276,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
rgba[3] = linearcol[3];
if (use_default_view)
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, NULL, &scene->display_settings);
else
- IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(rgba, rgba, &scene->view_settings, &scene->display_settings);
BLI_snprintf(str, sizeof(str), " | CM R:%-.4f G:%-.4f B:%-.4f", rgba[0], rgba[1], rgba[2]);
BLF_position(blf_mono_font, dx, dy, 0);
@@ -305,9 +314,9 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
if (color_manage) {
if (use_default_view)
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, NULL, &scene->display_settings);
else
- IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
+ IMB_colormanagement_pixel_to_display_space_v4(finalcol, col, &scene->view_settings, &scene->display_settings);
}
else {
copy_v4_v4(finalcol, col);
@@ -318,13 +327,18 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_rcti_init(&color_rect, dx, dx + (1.5f * UI_UNIT_X), 0.15f * UI_UNIT_Y, 0.85f * UI_UNIT_Y);
+ /* BLF uses immediate mode too, so we must reset our vertex format */
+ pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (channels == 4) {
rcti color_rect_half;
int color_quater_x, color_quater_y;
color_rect_half = color_rect;
color_rect_half.xmax = BLI_rcti_cent_x(&color_rect);
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ /* what color ??? */
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
color_rect_half = color_rect;
color_rect_half.xmin = BLI_rcti_cent_x(&color_rect);
@@ -332,31 +346,34 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
color_quater_x = BLI_rcti_cent_x(&color_rect_half);
color_quater_y = BLI_rcti_cent_y(&color_rect_half);
- glColor4ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, 255);
- glRecti(color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);
+ immUniformColor3ub(UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK, UI_ALPHA_CHECKER_DARK);
+ immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_rect_half.xmax, color_rect_half.ymax);
- glColor4ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, 255);
- glRecti(color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
- glRecti(color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
+ immUniformColor3ub(UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT, UI_ALPHA_CHECKER_LIGHT);
+ immRecti(pos, color_quater_x, color_quater_y, color_rect_half.xmax, color_rect_half.ymax);
+ immRecti(pos, color_rect_half.xmin, color_rect_half.ymin, color_quater_x, color_quater_y);
glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f));
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUniformColor4f(UNPACK3(finalcol), fp ? fp[3] : (cp[3] / 255.0f));
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
glDisable(GL_BLEND);
}
else {
- glColor3fv(finalcol);
- glRecti(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUniformColor3fv(finalcol);
+ immRecti(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
}
+ immUnbindProgram();
/* draw outline */
- glColor3ub(128, 128, 128);
- sdrawbox(color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformColor3ub(128, 128, 128);
+ imm_draw_line_box(pos, color_rect.xmin, color_rect.ymin, color_rect.xmax, color_rect.ymax);
+ immUnbindProgram();
dx += 1.75f * UI_UNIT_X;
- glColor3ub(255, 255, 255);
+ BLF_color3ub(blf_mono_font, 255, 255, 255);
if (channels == 1) {
if (fp) {
rgb_to_hsv(fp[0], fp[0], fp[0], &hue, &sat, &val);
@@ -375,7 +392,6 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
}
else if (channels >= 3) {
rgb_to_hsv(finalcol[0], finalcol[1], finalcol[2], &hue, &sat, &val);
@@ -399,70 +415,37 @@ void ED_image_draw_info(Scene *scene, ARegion *ar, bool color_manage, bool use_d
BLI_snprintf(str, sizeof(str), " L:%-.4f", lum);
BLF_position(blf_mono_font, dx, dy, 0);
BLF_draw_ascii(blf_mono_font, str, sizeof(str));
- dx += BLF_width(blf_mono_font, str, sizeof(str));
}
-
- (void)dx;
}
/* image drawing */
-
-static void sima_draw_alpha_pixels(float x1, float y1, int rectx, int recty, unsigned int *recti)
+static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *rect,
+ float zoomx, float zoomy)
{
-
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
- if (ENDIAN_ORDER == B_ENDIAN)
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_UNSIGNED_INT, recti);
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
-}
+ /* Slowwww */
+ int *recti = MEM_mallocN(rectx * recty * sizeof(int), "temp");
+ for (int a = rectx * recty - 1; a >= 0; a--) {
+ /* zbuffer values are signed, so we need to shift color range */
+ recti[a] = rect[a] * 0.5f + 0.5f;
+ }
-static void sima_draw_alpha_pixelsf(float x1, float y1, int rectx, int recty, float *rectf)
-{
- float *trectf = MEM_mallocN(rectx * recty * 4, "temp");
- int a, b;
-
- for (a = rectx * recty - 1, b = 4 * a + 3; a >= 0; a--, b -= 4)
- trectf[a] = rectf[b];
-
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, trectf);
- MEM_freeN(trectf);
- /* ogl trick below is slower... (on ATI 9600) */
-// glColorMask(1, 0, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 3);
-// glColorMask(0, 1, 0, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 2);
-// glColorMask(0, 0, 1, 0);
-// glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_RGBA, GL_FLOAT, rectf + 1);
-// glColorMask(1, 1, 1, 1);
-}
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
-static void sima_draw_zbuf_pixels(float x1, float y1, int rectx, int recty, int *recti)
-{
- /* zbuffer values are signed, so we need to shift color range */
- glPixelTransferf(GL_RED_SCALE, 0.5f);
- glPixelTransferf(GL_GREEN_SCALE, 0.5f);
- glPixelTransferf(GL_BLUE_SCALE, 0.5f);
- glPixelTransferf(GL_RED_BIAS, 0.5f);
- glPixelTransferf(GL_GREEN_BIAS, 0.5f);
- glPixelTransferf(GL_BLUE_BIAS, 0.5f);
-
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_INT, recti);
-
- glPixelTransferf(GL_RED_SCALE, 1.0f);
- glPixelTransferf(GL_GREEN_SCALE, 1.0f);
- glPixelTransferf(GL_BLUE_SCALE, 1.0f);
- glPixelTransferf(GL_RED_BIAS, 0.0f);
- glPixelTransferf(GL_GREEN_BIAS, 0.0f);
- glPixelTransferf(GL_BLUE_BIAS, 0.0f);
+ immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
+
+ MEM_freeN(recti);
}
-static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty, float *rect_float)
+static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rectx, int recty,
+ float *rect_float, float zoomx, float zoomy)
{
float bias, scale, *rectf, clipend;
int a;
-
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
+
if (scene->camera && scene->camera->type == OB_CAMERA) {
bias = ((Camera *)scene->camera->data)->clipsta;
clipend = ((Camera *)scene->camera->data)->clipend;
@@ -473,8 +456,8 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
scale = 0.01f;
clipend = 100.0f;
}
-
- rectf = MEM_mallocN(rectx * recty * 4, "temp");
+
+ rectf = MEM_mallocN(rectx * recty * sizeof(float), "temp");
for (a = rectx * recty - 1; a >= 0; a--) {
if (rect_float[a] > clipend)
rectf[a] = 0.0f;
@@ -485,92 +468,85 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
rectf[a] *= rectf[a];
}
}
- glaDrawPixelsSafe(x1, y1, rectx, recty, rectx, GL_LUMINANCE, GL_FLOAT, rectf);
-
- MEM_freeN(rectf);
-}
-static int draw_image_channel_offset(SpaceImage *sima)
-{
-#ifdef __BIG_ENDIAN__
- if (sima->flag & SI_SHOW_R) return 0;
- else if (sima->flag & SI_SHOW_G) return 1;
- else return 2;
-#else
- if (sima->flag & SI_SHOW_R) return 1;
- else if (sima->flag & SI_SHOW_G) return 2;
- else return 3;
-#endif
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
+
+ immDrawPixelsTex(x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
+
+ MEM_freeN(rectf);
}
static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
{
int x, y;
- /* set zoom */
- glPixelZoom(zoomx, zoomy);
-
glaDefine2DArea(&ar->winrct);
/* find window pixel coordinates of origin */
UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y);
/* this part is generic image display */
- if (sima->flag & SI_SHOW_ALPHA) {
- if (ibuf->rect)
- sima_draw_alpha_pixels(x, y, ibuf->x, ibuf->y, ibuf->rect);
- else if (ibuf->rect_float && ibuf->channels == 4)
- sima_draw_alpha_pixelsf(x, y, ibuf->x, ibuf->y, ibuf->rect_float);
- }
- else if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
+ if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) {
if (ibuf->zbuf)
- sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf);
+ sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy);
else if (ibuf->zbuf_float)
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float);
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->zbuf_float, zoomx, zoomy);
else if (ibuf->channels == 1)
- sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float);
+ sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float, zoomx, zoomy);
}
else {
+ int clip_max_x, clip_max_y;
+ UI_view2d_view_to_region(&ar->v2d,
+ ar->v2d.cur.xmax, ar->v2d.cur.ymax,
+ &clip_max_x, &clip_max_y);
+
if (sima->flag & SI_USE_ALPHA) {
+ imm_draw_checker_box(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
+
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy);
}
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) == 0) {
- int clip_max_x, clip_max_y;
- UI_view2d_view_to_region(&ar->v2d,
- ar->v2d.cur.xmax, ar->v2d.cur.ymax,
- &clip_max_x, &clip_max_y);
+ /* If RGBA display with color management */
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+
glaDrawImBuf_glsl_ctx_clipping(C, ibuf, x, y, GL_NEAREST,
- 0, 0, clip_max_x, clip_max_y);
+ 0, 0, clip_max_x, clip_max_y, zoomx, zoomy);
}
else {
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
unsigned char *display_buffer;
void *cache_handle;
-
- /* TODO(sergey): Ideally GLSL shading should be capable of either
- * disabling some channels or displaying buffer with custom offset.
- */
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (display_buffer != NULL) {
- int channel_offset = draw_image_channel_offset(sima);
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
- display_buffer - (4 - channel_offset));
- }
- if (cache_handle != NULL) {
- IMB_display_buffer_release(cache_handle);
+ ColorManagedViewSettings *view_settings;
+ ColorManagedDisplaySettings *display_settings;
+
+ if (sima->flag & SI_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (sima->flag & SI_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (sima->flag & SI_SHOW_B)
+ shuffle[2] = 1.0f;
+ else if (sima->flag & SI_SHOW_ALPHA)
+ shuffle[3] = 1.0f;
+
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle);
+
+ IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
+ display_buffer = IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle);
+
+ if (display_buffer) {
+ immDrawPixelsTex_clipping(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer,
+ 0, 0, clip_max_x, clip_max_y, zoomx, zoomy, NULL);
}
+
+ IMB_display_buffer_release(cache_handle);
}
if (sima->flag & SI_USE_ALPHA)
glDisable(GL_BLEND);
}
-
- /* reset zoom */
- glPixelZoom(1.0f, 1.0f);
}
static unsigned int *get_part_from_buffer(unsigned int *buffer, int width, short startx, short starty, short endx, short endy)
@@ -601,7 +577,7 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
unsigned int *rect;
int dx, dy, sx, sy, x, y;
void *cache_handle;
- int channel_offset = -1;
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* verify valid values, just leave this a while */
if (ima->xrep < 1) return;
@@ -615,8 +591,6 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
if (!display_buffer)
return;
- glPixelZoom(zoomx, zoomy);
-
if (sima->curtile >= ima->xrep * ima->yrep)
sima->curtile = ima->xrep * ima->yrep - 1;
@@ -628,24 +602,34 @@ static void draw_image_buffer_tiled(SpaceImage *sima, ARegion *ar, Scene *scene,
rect = get_part_from_buffer((unsigned int *)display_buffer, ibuf->x, sx, sy, sx + dx, sy + dy);
/* draw repeated */
- if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B)) != 0) {
- channel_offset = draw_image_channel_offset(sima);
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) != 0) {
+ if (sima->flag & SI_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (sima->flag & SI_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (sima->flag & SI_SHOW_B)
+ shuffle[2] = 1.0f;
+ else if (sima->flag & SI_SHOW_ALPHA)
+ shuffle[3] = 1.0f;
}
+
for (sy = 0; sy + dy <= ibuf->y; sy += dy) {
for (sx = 0; sx + dx <= ibuf->x; sx += dx) {
UI_view2d_view_to_region(&ar->v2d, fx + (float)sx / (float)ibuf->x, fy + (float)sy / (float)ibuf->y, &x, &y);
- if (channel_offset == -1) {
- glaDrawPixelsSafe(x, y, dx, dy, dx, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) {
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
}
else {
- glaDrawPixelsSafe(x, y, dx, dy, dx, GL_LUMINANCE, GL_UNSIGNED_INT,
- (unsigned char *)rect - (4 - channel_offset));
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle);
+
+ immDrawPixelsTex(x, y, dx, dy, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, rect, zoomx, zoomy, NULL);
}
}
}
- glPixelZoom(1.0f, 1.0f);
-
IMB_display_buffer_release(cache_handle);
MEM_freeN(rect);
@@ -701,101 +685,62 @@ void draw_image_sample_line(SpaceImage *sima)
if (sima->sample_line_hist.flag & HISTO_FLAG_SAMPLELINE) {
Histogram *hist = &sima->sample_line_hist;
- glBegin(GL_LINES);
- glColor3ub(0, 0, 0);
- glVertex2fv(hist->co[0]);
- glVertex2fv(hist->co[1]);
- glEnd();
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immBegin(GL_LINES, 2);
+ immUniformColor3ub(0, 0, 0);
+ immVertex2fv(pos, hist->co[0]);
+ immVertex2fv(pos, hist->co[1]);
+ immEnd();
setlinestyle(1);
- glBegin(GL_LINES);
- glColor3ub(255, 255, 255);
- glVertex2fv(hist->co[0]);
- glVertex2fv(hist->co[1]);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immUniformColor3ub(255, 255, 255);
+ immVertex2fv(pos, hist->co[0]);
+ immVertex2fv(pos, hist->co[1]);
+ immEnd();
setlinestyle(0);
- }
-}
-
-static unsigned char *get_alpha_clone_image(const bContext *C, Scene *scene, int *width, int *height)
-{
- Brush *brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
- ImBuf *ibuf;
- unsigned int size, alpha;
- unsigned char *display_buffer;
- unsigned char *rect, *cp;
- void *cache_handle;
-
- if (!brush || !brush->clone.image)
- return NULL;
-
- ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
-
- if (!ibuf)
- return NULL;
+ immUnbindProgram();
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- if (!display_buffer) {
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- IMB_display_buffer_release(cache_handle);
-
- return NULL;
}
-
- rect = MEM_dupallocN(display_buffer);
-
- IMB_display_buffer_release(cache_handle);
-
- if (!rect) {
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
- return NULL;
- }
-
- *width = ibuf->x;
- *height = ibuf->y;
-
- size = (*width) * (*height);
- alpha = (unsigned char)255 * brush->clone.alpha;
- cp = rect;
-
- while (size-- > 0) {
- cp[3] = alpha;
- cp += 4;
- }
-
- BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
-
- return rect;
}
static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy)
{
Brush *brush;
- int x, y, w, h;
- unsigned char *clonerect;
+ int x, y;
+ ImBuf *ibuf;
brush = BKE_paint_brush(&scene->toolsettings->imapaint.paint);
- if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE)) {
- /* this is not very efficient, but glDrawPixels doesn't allow
- * drawing with alpha */
- clonerect = get_alpha_clone_image(C, scene, &w, &h);
+ if (brush && (brush->imagepaint_tool == PAINT_TOOL_CLONE) && brush->clone.image) {
+ ibuf = BKE_image_acquire_ibuf(brush->clone.image, NULL, NULL);
- if (clonerect) {
+ if (ibuf) {
+ void *cache_handle = NULL;
+ float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha};
UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y);
- glPixelZoom(zoomx, zoomy);
+ unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+
+ if (!display_buffer) {
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
+ return;
+ }
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glaDrawPixelsSafe(x, y, w, h, w, GL_RGBA, GL_UNSIGNED_BYTE, clonerect);
- glDisable(GL_BLEND);
- glPixelZoom(1.0, 1.0);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer, zoomx, zoomy, col);
+
+ glDisable(GL_BLEND);
- MEM_freeN(clonerect);
+ BKE_image_release_ibuf(brush->clone.image, ibuf, NULL);
+ IMB_display_buffer_release(cache_handle);
}
}
}
@@ -891,23 +836,6 @@ void draw_image_main(const bContext *C, ARegion *ar)
if (show_paint)
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
- /* XXX integrate this code */
-#if 0
- if (ibuf) {
- float xoffs = 0.0f, yoffs = 0.0f;
-
- if (image_preview_active(sa, &xim, &yim)) {
- xoffs = scene->r.disprect.xmin;
- yoffs = scene->r.disprect.ymin;
- glColor3ub(0, 0, 0);
- calc_image_view(sima, 'f');
- myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
- glRectf(0.0f, 0.0f, 1.0f, 1.0f);
- glLoadIdentity();
- }
- }
-#endif
-
if (show_viewer) {
BLI_unlock_thread(LOCK_DRAW_IMAGE);
}
@@ -969,8 +897,12 @@ void draw_image_cache(const bContext *C, ARegion *ar)
/* Draw current frame. */
x = (cfra - sfra) / (efra - sfra + 1) * ar->winx;
- UI_ThemeColor(TH_CFRAME);
- glRecti(x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CFRAME);
+ immRecti(pos, x, 0, x + ceilf(framelen), 8 * UI_DPI_FAC);
+ immUnbindProgram();
+
ED_region_cache_draw_curfra_label(cfra, x, 8.0f * UI_DPI_FAC);
if (mask != NULL) {
diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c
index 8f2f6595408..f19a6d64faa 100644
--- a/source/blender/editors/space_image/image_edit.c
+++ b/source/blender/editors/space_image/image_edit.c
@@ -374,10 +374,10 @@ bool ED_space_image_show_uvedit(SpaceImage *sima, Object *obedit)
}
/* matches clip function */
-bool ED_space_image_check_show_maskedit(Scene *scene, SpaceImage *sima)
+bool ED_space_image_check_show_maskedit(SceneLayer *sl, SpaceImage *sima)
{
/* check editmode - this is reserved for UV editing */
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
if (ob && ob->mode & OB_MODE_EDIT && ED_space_image_show_uvedit(sima, ob)) {
return false;
}
@@ -390,8 +390,8 @@ int ED_space_image_maskedit_poll(bContext *C)
SpaceImage *sima = CTX_wm_space_image(C);
if (sima) {
- Scene *scene = CTX_data_scene(C);
- return ED_space_image_check_show_maskedit(scene, sima);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ return ED_space_image_check_show_maskedit(sl, sima);
}
return false;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 324a3cb13b7..534b131c38e 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -792,6 +792,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
SpaceImage *sima;
ARegion *ar;
Scene *scene;
+ SceneLayer *sl;
Object *obedit;
Image *ima;
@@ -799,6 +800,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
sima = CTX_wm_space_image(C);
ar = CTX_wm_region(C);
scene = CTX_data_scene(C);
+ sl = CTX_data_scene_layer(C);
obedit = CTX_data_edit_object(C);
ima = ED_space_image(sima);
@@ -810,7 +812,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
}
- else if (ED_space_image_check_show_maskedit(scene, sima)) {
+ else if (ED_space_image_check_show_maskedit(sl, sima)) {
if (!ED_mask_selected_minmax(C, min, max)) {
return OPERATOR_CANCELLED;
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 6ddf78290aa..f1176acfa94 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -45,10 +45,13 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "DEG_depsgraph.h"
+
#include "IMB_imbuf_types.h"
#include "ED_image.h"
@@ -535,6 +538,7 @@ static void image_listener(bScreen *sc, ScrArea *sa, wmNotifier *wmn)
case ND_TRANSFORM:
case ND_MODIFIER:
{
+ TODO_LAYER_CONTEXT; /* need to use OBACT_NEW */
Object *ob = OBACT;
if (ob && (ob == wmn->reference) && (ob->mode & OB_MODE_EDIT)) {
if (sima->lock && (sima->flag & SI_DRAWSHADOW)) {
@@ -684,9 +688,11 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
SpaceImage *sima = CTX_wm_space_image(C);
Object *obact = CTX_data_active_object(C);
Object *obedit = CTX_data_edit_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
Mask *mask = NULL;
bool curve = false;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View2D *v2d = &ar->v2d;
//View2DScrollers *scrollers;
float col[3];
@@ -722,7 +728,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
- ED_uvedit_draw_main(sima, ar, scene, obedit, obact);
+ ED_uvedit_draw_main(sima, ar, scene, sl, obedit, obact, depsgraph);
/* check for mask (delay draw) */
if (ED_space_image_show_uvedit(sima, obedit)) {
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 8ee488ac591..1872a8a0545 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -207,7 +207,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, -initial_offset);
- // glColor4ub(255, 0, 0, 96); // debug
+ /* BLF_color3ub(cdc->font_id, 255, 0, 0); // debug */
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
}
@@ -222,7 +222,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
if (cdc->sel[0] != cdc->sel[1]) {
console_step_sel(cdc, len);
- // glColor4ub(0, 255, 0, 96); // debug
+ /* BLF_color3ub(cdc->font_id, 0, 255, 0); // debug */
console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel);
}
@@ -251,6 +251,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
immUnbindProgram();
}
+ BLF_color3ubv(cdc->font_id, fg);
BLF_position(cdc->font_id, cdc->xy[0], cdc->lofs + cdc->xy[1], 0);
BLF_draw_mono(cdc->font_id, str, str_len, cdc->cwidth);
@@ -260,7 +261,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str
isel[0] = str_len - cdc->sel[1];
isel[1] = str_len - cdc->sel[0];
- // glColor4ub(255, 255, 0, 96); // debug
+ /* BLF_color3ub(cdc->font_id, 255, 255, 0); // debug */
console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel);
console_step_sel(cdc, -(str_len + 1));
}
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index e744a39fde9..ae9a9e3a36b 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -1,4 +1,3 @@
-
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -150,11 +149,11 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, float y, floa
immBegin(PRIM_POINTS, key_ct);
/* - disregard the selection status of keyframes so they draw a certain way
- * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
+ * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
*/
for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
- draw_keyframe_shape(ak->cfra, y, 3.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f,
- pos_id, size_id, color_id, outline_color_id);
+ draw_keyframe_shape(ak->cfra, y, 6.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f,
+ pos_id, size_id, color_id, outline_color_id);
}
immEnd();
@@ -308,6 +307,7 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, uns
*/
for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
+ CLAMP(y, 0.0f, 1.0f);
immVertex2f(pos, cfra, ((y * yheight) + yminc));
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 5940ed5f0c1..c74dc3f5b3c 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -50,11 +50,11 @@
#include "BLF_api.h"
#include "BLT_translation.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -353,6 +353,7 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
const int font_size = data->label_size / aspect;
const float margin = (float)(NODE_DY / 4);
int label_height;
+ unsigned char color[3];
nodeLabel(ntree, node, label, sizeof(label));
@@ -361,7 +362,8 @@ static void node_draw_frame_label(bNodeTree *ntree, bNode *node, const float asp
BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */
/* title color */
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ UI_GetThemeColorBlendShade3ubv(TH_TEXT, color_id, 0.4f, 10, color);
+ BLF_color3ubv(fontid, color);
width = BLF_width(fontid, label, sizeof(label));
ascender = BLF_ascender(fontid);
@@ -545,10 +547,6 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
char showname[128]; /* 128 used below */
rctf *rct = &node->totr;
-#if 0 /* UNUSED */
- float size = NODE_REROUTE_SIZE;
-#endif
-
/* skip if out of view */
if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax)
@@ -562,11 +560,14 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
* selection state is indicated by socket outline below!
*/
#if 0
+ float size = NODE_REROUTE_SIZE;
+
/* body */
+ float debug_color[4];
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_ThemeColor4(TH_NODE);
+ UI_GetThemeColor4fv(TH_NODE, debug_color);
glEnable(GL_BLEND);
- UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
+ UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
glDisable(GL_BLEND);
/* outline active and selected emphasis */
@@ -574,11 +575,13 @@ static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
/* using different shades of TH_TEXT_HI for the empasis, like triangle */
- if (node->flag & NODE_ACTIVE)
- UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
- else
- UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
- UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
+ if (node->flag & NODE_ACTIVE) {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, 0, -40, debug_color);
+ }
+ else {
+ UI_GetThemeColorShadeAlpha4fv(TH_TEXT_HI, -20, -120, debug_color);
+ }
+ UI_draw_roundbox_gl_mode(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size, debug_color);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_BLEND);
@@ -1278,9 +1281,6 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
PropertyRNA *prop;
const char *layer_name;
char scene_name[MAX_ID_NAME - 2];
- wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1);
-
- BLI_assert(ot != 0);
uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
@@ -1297,11 +1297,9 @@ static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, Point
scn_ptr = RNA_pointer_get(ptr, "scene");
RNA_string_get(&scn_ptr, "name", scene_name);
- WM_operator_properties_create_ptr(&op_ptr, ot);
+ op_ptr = uiItemFullO(row, "RENDER_OT_render", "", ICON_RENDER_STILL, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&op_ptr, "layer", layer_name);
RNA_string_set(&op_ptr, "scene", scene_name);
- uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
-
}
@@ -1750,6 +1748,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
Scene *scene = CTX_data_scene(C);
PointerRNA imfptr = RNA_pointer_get(ptr, "format");
PointerRNA active_input_ptr, op_ptr;
+ wmOperatorType *ot;
uiLayout *row, *col;
int active_index;
const bool multilayer = RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER;
@@ -1788,11 +1787,10 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
active_input_ptr.id.data = ptr->id.data;
col = uiLayoutColumn(row, true);
- op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
- ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false);
+ op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 1);
- op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
- ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ op_ptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&op_ptr, "direction", 2);
if (active_input_ptr.data) {
@@ -2124,14 +2122,7 @@ static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), Poi
static void node_composit_buts_switch_view_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *UNUSED(ptr))
{
- PointerRNA op_ptr;
- wmOperatorType *ot = WM_operatortype_find("NODE_OT_switch_view_update", 1);
-
- BLI_assert(ot != 0);
-
- WM_operator_properties_create_ptr(&op_ptr, ot);
-
- uiItemFullO_ptr(layout, ot, "Update Views", ICON_FILE_REFRESH, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ uiItemFullO(layout, "NODE_OT_switch_view_update", "Update Views", ICON_FILE_REFRESH, NULL, WM_OP_INVOKE_DEFAULT, 0);
}
static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -2176,8 +2167,8 @@ static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNo
const float cx = x + snode->zoom * backdropWidth * node->custom3;
const float cy = y + snode->zoom * backdropHeight * node->custom4;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2221,8 +2212,8 @@ static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bN
y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -2265,8 +2256,8 @@ static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop
y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -3178,6 +3169,7 @@ void ED_init_node_socket_type_virtual(bNodeSocketType *stype)
void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeInstanceKey parent_key)
{
bNodeInstanceKey active_viewer_key = (snode->nodetree ? snode->nodetree->active_viewer_key : NODE_INSTANCE_KEY_NONE);
+ float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f};
Image *ima;
void *lock;
ImBuf *ibuf;
@@ -3192,12 +3184,12 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
if (ibuf) {
float x, y;
-
+
glMatrixMode(GL_PROJECTION);
- glPushMatrix();
+ gpuPushMatrix();
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
-
+ gpuPushMatrix();
+
/* somehow the offset has to be calculated inverse */
glaDefine2DArea(&ar->winrct);
@@ -3210,60 +3202,37 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
unsigned char *display_buffer = NULL;
void *cache_handle = NULL;
- if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) {
- int ofs;
-
- display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
+ if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B | SNODE_SHOW_ALPHA)) {
-#ifdef __BIG_ENDIAN__
- if (snode->flag & SNODE_SHOW_R) ofs = 0;
- else if (snode->flag & SNODE_SHOW_G) ofs = 1;
- else ofs = 2;
-#else
- if (snode->flag & SNODE_SHOW_R) ofs = 1;
- else if (snode->flag & SNODE_SHOW_G) ofs = 2;
- else ofs = 3;
-#endif
-
- glPixelZoom(snode->zoom, snode->zoom);
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
-
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT,
- display_buffer - (4 - ofs));
-
- glPixelZoom(1.0f, 1.0f);
- }
- else if (snode->flag & SNODE_SHOW_ALPHA) {
display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
-
- glPixelZoom(snode->zoom, snode->zoom);
- /* swap bytes, so alpha is most significant one, then just draw it as luminance int */
-#ifdef __BIG_ENDIAN__
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
-#endif
- glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_LUMINANCE, GL_UNSIGNED_INT, display_buffer);
-
-#ifdef __BIG_ENDIAN__
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
-#endif
- glPixelZoom(1.0f, 1.0f);
+
+ if (snode->flag & SNODE_SHOW_R)
+ shuffle[0] = 1.0f;
+ else if (snode->flag & SNODE_SHOW_G)
+ shuffle[1] = 1.0f;
+ else if (snode->flag & SNODE_SHOW_B)
+ shuffle[2] = 1.0f;
+ else
+ shuffle[3] = 1.0f;
+
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, shuffle);
+
+ immDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
+ display_buffer, snode->zoom, snode->zoom, NULL);
+
+ GPU_shader_unbind();
}
else if (snode->flag & SNODE_USE_ALPHA) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPixelZoom(snode->zoom, snode->zoom);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
-
- glPixelZoom(1.0f, 1.0f);
+
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
+
glDisable(GL_BLEND);
}
else {
- glPixelZoom(snode->zoom, snode->zoom);
-
- glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST);
-
- glPixelZoom(1.0f, 1.0f);
+ glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST, snode->zoom, snode->zoom);
}
if (cache_handle)
@@ -3288,20 +3257,26 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
viewer_border->ymin < viewer_border->ymax)
{
rcti pixel_border;
- UI_ThemeColor(TH_ACTIVE);
BLI_rcti_init(&pixel_border,
x + snode->zoom * viewer_border->xmin * ibuf->x,
x + snode->zoom * viewer_border->xmax * ibuf->x,
y + snode->zoom * viewer_border->ymin * ibuf->y,
y + snode->zoom * viewer_border->ymax * ibuf->y);
- glaDrawBorderCorners(&pixel_border, 1.0f, 1.0f);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE);
+
+ immDrawBorderCorners(pos, &pixel_border, 1.0f, 1.0f);
+
+ immUnbindProgram();
}
}
-
+
glMatrixMode(GL_PROJECTION);
- glPopMatrix();
+ gpuPopMatrix();
glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix();
}
BKE_image_release_ibuf(ima, ibuf, lock);
@@ -3414,6 +3389,7 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
float arrow[2], arrow1[2], arrow2[2];
const float px_fac = UI_DPI_WINDOW_FAC;
glGetFloatv(GL_LINE_WIDTH, &linew);
+ unsigned int pos;
/* we can reuse the dist variable here to increment the GL curve eval amount*/
dist = 1.0f / (float)LINK_RESOL;
@@ -3437,141 +3413,89 @@ void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
arrow[0] = coord_array[LINK_ARROW][0];
arrow[1] = coord_array[LINK_ARROW][1];
}
+
+ if (do_triple || drawarrow || (!do_shaded)) {
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+
if (do_triple) {
- UI_ThemeColorShadeAlpha(th_col3, -80, -120);
+ immUniformThemeColorShadeAlpha(th_col3, -80, -120);
glLineWidth(4.0f * px_fac);
-
- glBegin(GL_LINE_STRIP);
+
+ immBegin(GL_LINE_STRIP, (LINK_RESOL + 1));
+
for (i = 0; i <= LINK_RESOL; i++) {
- glVertex2fv(coord_array[i]);
+ immVertex2fv(pos, coord_array[i]);
}
- glEnd();
+
+ immEnd();
+
if (drawarrow) {
- glBegin(GL_LINE_STRIP);
- glVertex2fv(arrow1);
- glVertex2fv(arrow);
- glVertex2fv(arrow2);
- glEnd();
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2fv(pos, arrow1);
+ immVertex2fv(pos, arrow);
+ immVertex2fv(pos, arrow2);
+ immEnd();
}
}
-
- /* XXX using GL_LINES for shaded node lines is a workaround
- * for Intel hardware, this breaks with GL_LINE_STRIP and
- * changing color in begin/end blocks.
- */
+
glLineWidth(1.5f * px_fac);
- if (do_shaded) {
- glBegin(GL_LINES);
- for (i = 0; i < LINK_RESOL; i++) {
- UI_ThemeColorBlend(th_col1, th_col2, spline_step);
- glVertex2fv(coord_array[i]);
-
- UI_ThemeColorBlend(th_col1, th_col2, spline_step + dist);
- glVertex2fv(coord_array[i + 1]);
-
- spline_step += dist;
- }
- glEnd();
+
+ if (drawarrow) {
+ immUniformThemeColorBlend(th_col1, th_col2, 0.5f);
+
+ immBegin(GL_LINE_STRIP, 3);
+ immVertex2fv(pos, arrow1);
+ immVertex2fv(pos, arrow);
+ immVertex2fv(pos, arrow2);
+ immEnd();
}
- else {
- UI_ThemeColor(th_col1);
- glBegin(GL_LINE_STRIP);
+
+ if (!do_shaded) {
+ immUniformThemeColor(th_col1);
+
+ immBegin(GL_LINE_STRIP, (LINK_RESOL + 1));
+
for (i = 0; i <= LINK_RESOL; i++) {
- glVertex2fv(coord_array[i]);
+ immVertex2fv(pos, coord_array[i]);
}
- glEnd();
+
+ immEnd();
}
-
- if (drawarrow) {
- glBegin(GL_LINE_STRIP);
- glVertex2fv(arrow1);
- glVertex2fv(arrow);
- glVertex2fv(arrow2);
- glEnd();
+
+ if (do_triple || drawarrow || (!do_shaded)) {
+ immUnbindProgram();
}
-
- glDisable(GL_LINE_SMOOTH);
- }
-}
-#if 0 /* not used in 2.5x yet */
-static void node_link_straight_points(View2D *UNUSED(v2d), SpaceNode *snode, bNodeLink *link, float coord_array[][2])
-{
- if (link->fromsock) {
- coord_array[0][0] = link->fromsock->locx;
- coord_array[0][1] = link->fromsock->locy;
- }
- else {
- if (snode == NULL) return;
- coord_array[0][0] = snode->mx;
- coord_array[0][1] = snode->my;
- }
- if (link->tosock) {
- coord_array[1][0] = link->tosock->locx;
- coord_array[1][1] = link->tosock->locy;
- }
- else {
- if (snode == NULL) return;
- coord_array[1][0] = snode->mx;
- coord_array[1][1] = snode->my;
- }
-}
+ if (do_shaded) {
+ unsigned char col[3];
-void node_draw_link_straight(View2D *v2d, SpaceNode *snode, bNodeLink *link,
- int th_col1, int do_shaded, int th_col2, int do_triple, int th_col3)
-{
- float coord_array[2][2];
- int i;
-
- node_link_straight_points(v2d, snode, link, coord_array);
-
- glEnable(GL_LINE_SMOOTH);
-
- if (do_triple) {
- UI_ThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f);
-
- glBegin(GL_LINES);
- glVertex2fv(coord_array[0]);
- glVertex2fv(coord_array[1]);
- glEnd();
- }
-
- UI_ThemeColor(th_col1);
- glLineWidth(1.5f);
-
- /* XXX using GL_LINES for shaded node lines is a workaround
- * for Intel hardware, this breaks with GL_LINE_STRIP and
- * changing color in begin/end blocks.
- */
- if (do_shaded) {
- glBegin(GL_LINES);
- for (i = 0; i < LINK_RESOL - 1; ++i) {
- float t = (float)i / (float)(LINK_RESOL - 1);
- UI_ThemeColorBlend(th_col1, th_col2, t);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
-
- t = (float)(i + 1) / (float)(LINK_RESOL - 1);
- UI_ThemeColorBlend(th_col1, th_col2, t);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
- }
- glEnd();
- }
- else {
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < LINK_RESOL; ++i) {
- float t = (float)i / (float)(LINK_RESOL - 1);
- glVertex2f((1.0f - t) * coord_array[0][0] + t * coord_array[1][0],
- (1.0f - t) * coord_array[0][1] + t * coord_array[1][1]);
+ VertexFormat *format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+ immBegin(GL_LINE_STRIP, (LINK_RESOL + 1));
+
+ for (i = 0; i <= LINK_RESOL; i++) {
+ UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col);
+ immAttrib3ubv(color, col);
+
+ immVertex2fv(pos, coord_array[i]);
+
+ spline_step += dist;
+ }
+
+ immEnd();
+
+ immUnbindProgram();
}
- glEnd();
+
+ glDisable(GL_LINE_SMOOTH);
}
-
- glDisable(GL_LINE_SMOOTH);
}
-#endif
/* note; this is used for fake links in groups too */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c
index d49df2afbd4..bcd0f6623e1 100644
--- a/source/blender/editors/space_node/node_add.c
+++ b/source/blender/editors/space_node/node_add.c
@@ -44,6 +44,8 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
+#include "BKE_texture.h"
#include "ED_node.h" /* own include */
#include "ED_screen.h"
@@ -312,7 +314,10 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
switch (snode->nodetree->type) {
case NTREE_SHADER:
- type = SH_NODE_TEX_IMAGE;
+ if (BKE_scene_use_new_shading_nodes(CTX_data_scene(C)))
+ type = SH_NODE_TEX_IMAGE;
+ else
+ type = SH_NODE_TEXTURE;
break;
case NTREE_TEXTURE:
type = TEX_NODE_IMAGE;
@@ -333,7 +338,14 @@ static int node_add_file_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- node->id = (ID *)ima;
+ if (type == SH_NODE_TEXTURE) {
+ Tex *tex = BKE_texture_add(CTX_data_main(C), DATA_(ima->id.name));
+ tex->ima = ima;
+ node->id = (ID *)tex;
+ WM_event_add_notifier(C, NC_TEXTURE | NA_ADDED, node->id);
+ }
+ else
+ node->id = (ID *)ima;
/* When adding new image file via drag-drop we need to load imbuf in order
* to get proper image source.
diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c
index f0567924edd..925298451ce 100644
--- a/source/blender/editors/space_node/node_buttons.c
+++ b/source/blender/editors/space_node/node_buttons.c
@@ -133,6 +133,7 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
int in_out;
uiLayout *layout = pa->layout, *row, *split, *col;
PointerRNA ptr, sockptr, opptr;
+ wmOperatorType *ot;
if (!ntree)
return;
@@ -146,23 +147,25 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa)
split = uiLayoutRow(row, true);
col = uiLayoutColumn(split, true);
+ ot = WM_operatortype_find("NODE_OT_tree_socket_add", false);
uiItemL(col, IFACE_("Inputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input",
NULL, 0, 0, 0, 0);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_IN);
col = uiLayoutColumn(split, true);
uiItemL(col, IFACE_("Outputs:"), ICON_NONE);
uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output",
NULL, 0, 0, 0, 0);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "in_out", SOCK_OUT);
+ ot = WM_operatortype_find("NODE_OT_tree_socket_move", false);
col = uiLayoutColumn(row, true);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_UP, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 1);
- opptr = uiItemFullO(col, "NODE_OT_tree_socket_move", "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ opptr = uiItemFullO_ptr(col, ot, "", ICON_TRIA_DOWN, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_enum_set(&opptr, "direction", 2);
if (sock) {
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 80b19176c90..fa23f8f77b4 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -51,11 +51,11 @@
#include "BLF_api.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_draw.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -705,15 +705,17 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */
- glColor4f(1.0, 1.0, 1.0, 1.0);
- glPixelZoom(scale, scale);
- glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect);
- glPixelZoom(1.0f, 1.0f);
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect,
+ scale, scale, NULL);
glDisable(GL_BLEND);
- UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
- fdrawbox(draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, +100);
+ imm_draw_line_box(pos, draw_rect.xmin, draw_rect.ymin, draw_rect.xmax, draw_rect.ymax);
+ immUnbindProgram();
}
/* common handle function for operator buttons that need to select the node first */
@@ -748,11 +750,18 @@ void node_draw_shadow(SpaceNode *snode, bNode *node, float radius, float alpha)
void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *node, bool draw_outputs, bool select_all)
{
+ const unsigned int total_input_ct = BLI_listbase_count(&node->inputs);
+ const unsigned int total_output_ct = BLI_listbase_count(&node->outputs);
+
+ if (total_input_ct + total_output_ct == 0) {
+ return;
+ }
+
PointerRNA node_ptr;
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
- float xscale, yscale;
- UI_view2d_scale_get(v2d, &xscale, &yscale);
+ float scale;
+ UI_view2d_scale_get(v2d, &scale, NULL);
VertexFormat *format = immVertexFormat();
unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
@@ -761,17 +770,17 @@ void node_draw_sockets(View2D *v2d, const bContext *C, bNodeTree *ntree, bNode *
glEnable(GL_BLEND);
GPU_enable_program_point_size();
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
/* set handle size */
- immUniform1f("size", 2.0f * NODE_SOCKSIZE * xscale); // 2 * size to have diameter
+ immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
if (!select_all) {
/* outline for unselected sockets */
immUniform1f("outlineWidth", 1.0f);
immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
- immBeginAtMost(GL_POINTS, BLI_listbase_count(&node->inputs) + BLI_listbase_count(&node->outputs));
+ immBeginAtMost(GL_POINTS, total_input_ct + total_output_ct);
}
/* socket inputs */
@@ -878,17 +887,19 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
/* shadow */
node_draw_shadow(snode, node, BASIS_RAD, 1.0f);
- /* header uses color from backdrop, but we make it opaqie */
- if (color_id == TH_NODE) {
- UI_GetThemeColorShade3fv(color_id, -20, color);
- }
- else
- UI_GetThemeColor4fv(color_id, color);
-
- if (node->flag & NODE_MUTED)
+ if (node->flag & NODE_MUTED) {
UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
-
-
+ }
+ else {
+ /* header uses color from backdrop, but we make it opaque */
+ if (color_id == TH_NODE) {
+ UI_GetThemeColorShade3fv(color_id, -20, color);
+ color[3] = 1.0f;
+ }
+ else {
+ UI_GetThemeColor4fv(color_id, color);
+ }
+ }
#ifdef WITH_COMPOSITOR
if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) {
@@ -934,10 +945,12 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
}
/* title */
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
/* open/close entirely? */
{
@@ -952,13 +965,9 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v');
+ UI_draw_icon_tri(rct->xmin + 0.5f * U.widget_unit, rct->ymax - NODE_DY / 2.0f, 'v', color);
}
-#if 0 /* this isn't doing anything for the label, so commenting out */
- UI_ThemeColor((node->flag & SELECT) ? TH_TEXT_HI : TH_TEXT);
-#endif
-
nodeLabel(ntree, node, showname, sizeof(showname));
//if (node->flag & NODE_MUTED)
@@ -973,10 +982,11 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if (!nodeIsRegistered(node))
UI_GetThemeColor4fv(TH_REDALERT, color); /* use warning color to indicate undefined types */
else if (node->flag & NODE_CUSTOM_COLOR) {
- rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
+ rgba_float_args_set(color, node->color[0], node->color[1], node->color[2], 1.0f);
}
else
UI_GetThemeColor4fv(TH_NODE, color);
+
glEnable(GL_BLEND);
UI_draw_roundbox_corner_set(UI_CNR_BOTTOM_LEFT | UI_CNR_BOTTOM_RIGHT);
UI_draw_roundbox(rct->xmin, rct->ymin, rct->xmax, rct->ymax - NODE_DY, BASIS_RAD, color);
@@ -1028,17 +1038,18 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
float color[4];
char showname[128]; /* 128 is used below */
View2D *v2d = &ar->v2d;
- float xscale, yscale;
+ float scale;
- UI_view2d_scale_get(v2d, &xscale, &yscale);
+ UI_view2d_scale_get(v2d, &scale, NULL);
/* shadow */
node_draw_shadow(snode, node, hiddenrad, 1.0f);
/* body */
- UI_ThemeColor(color_id);
if (node->flag & NODE_MUTED)
UI_GetThemeColorBlendShade4fv(color_id, TH_REDALERT, 0.5f, 0, color);
+ else
+ UI_GetThemeColor4fv(color_id, color);
#ifdef WITH_COMPOSITOR
if (ntree->type == NTREE_COMPOSIT && (snode->flag & SNODE_SHOW_HIGHLIGHT)) {
@@ -1077,10 +1088,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
/* title */
- if (node->flag & SELECT)
- UI_ThemeColor(TH_SELECT);
- else
- UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
+ if (node->flag & SELECT) {
+ UI_GetThemeColor4fv(TH_SELECT, color);
+ }
+ else {
+ UI_GetThemeColorBlendShade4fv(TH_SELECT, color_id, 0.4f, 10, color);
+ }
/* open entirely icon */
{
@@ -1095,15 +1108,13 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
UI_block_emboss_set(node->block, UI_EMBOSS);
/* custom draw function for this button */
- UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h');
+ UI_draw_icon_tri(rct->xmin + 10.0f, centy, 'h', color);
}
/* disable lines */
if (node->flag & NODE_MUTED)
node_draw_mute_line(&ar->v2d, snode, node);
- UI_ThemeColor((node->flag & SELECT) ? TH_SELECT : TH_TEXT);
-
if (node->miniwidth > 0.0f) {
nodeLabel(ntree, node, showname, sizeof(showname));
@@ -1117,15 +1128,32 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
}
/* scale widget thing */
- UI_ThemeColorShade(color_id, -10);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColorShade(color_id, -10);
dx = 10.0f;
- fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f);
- fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
-
- UI_ThemeColorShade(color_id, +30);
+
+ immBegin(PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUniformThemeColorShade(color_id, 30);
dx -= snode->aspect;
- fdrawline(rct->xmax - dx, centy - 4.0f, rct->xmax - dx, centy + 4.0f);
- fdrawline(rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+
+ immBegin(PRIM_LINES, 4);
+ immVertex2f(pos, rct->xmax - dx, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx, centy + 4.0f);
+
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy - 4.0f);
+ immVertex2f(pos, rct->xmax - dx - 3.0f * snode->aspect, centy + 4.0f);
+ immEnd();
+
+ immUnbindProgram();
node_draw_sockets(v2d, C, ntree, node, true, false);
@@ -1175,10 +1203,20 @@ void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2])
void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key)
{
+ glMatrixMode(GL_PROJECTION);
+ gpuPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPushMatrix();
+
if (node->flag & NODE_HIDDEN)
node_draw_hidden(C, ar, snode, ntree, node, key);
else
node_draw_basis(C, ar, snode, ntree, node, key);
+
+ glMatrixMode(GL_PROJECTION);
+ gpuPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPopMatrix();
}
static void node_update(const bContext *C, bNodeTree *ntree, bNode *node)
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index ffe510016ff..fdfe316f5ed 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -582,7 +582,7 @@ void snode_set_context(const bContext *C)
}
}
- if (snode->nodetree != ntree || snode->id != id || snode->from != from) {
+ if (snode->nodetree != ntree || snode->id != id || snode->from != from || snode->treepath.last == NULL) {
ED_node_tree_start(snode, ntree, id, from);
}
@@ -1069,12 +1069,9 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so
/* check if we click in a socket */
for (node = snode->edittree->nodes.first; node; node = node->next) {
-
- rect.xmin = cursor[0] - (NODE_SOCKSIZE + 4);
- rect.ymin = cursor[1] - (NODE_SOCKSIZE + 4);
- rect.xmax = cursor[0] + (NODE_SOCKSIZE + 4);
- rect.ymax = cursor[1] + (NODE_SOCKSIZE + 4);
-
+
+ BLI_rctf_init_pt_radius(&rect, cursor, NODE_SOCKSIZE + 4);
+
if (!(node->flag & NODE_HIDDEN)) {
/* extra padding inside and out - allow dragging on the text areas too */
if (in_out == SOCK_IN) {
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index 289d6e715e1..a9d630c31e5 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -37,12 +37,14 @@ set(INC_SYS
)
set(SRC
+ outliner_collections.c
outliner_draw.c
outliner_edit.c
outliner_ops.c
outliner_select.c
outliner_tools.c
outliner_tree.c
+ outliner_utils.c
space_outliner.c
outliner_intern.h
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
new file mode 100644
index 00000000000..e9c49ffdb14
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -0,0 +1,458 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation, Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_outliner/outliner_collections.c
+ * \ingroup spoutliner
+ */
+
+#include "BKE_context.h"
+#include "BKE_collection.h"
+#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
+#include "BKE_report.h"
+
+#include "BLI_listbase.h"
+
+#include "ED_screen.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_resources.h"
+
+#include "outliner_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+
+static LayerCollection *outliner_collection_active(bContext *C)
+{
+ TODO_LAYER_OPERATORS;
+ /* consider that we may have overrides or objects active
+ * leading to no active collections */
+ return CTX_data_layer_collection(C);
+}
+
+SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te)
+{
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == TSE_SCENE_COLLECTION) {
+ return te->directdata;
+ }
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ LayerCollection *lc = te->directdata;
+ return lc->scene_collection;
+ }
+
+ return NULL;
+}
+
+#if 0
+static CollectionOverride *outliner_override_active(bContext *UNUSED(C))
+{
+ TODO_LAYER_OPERATORS;
+ TODO_LAYER_OVERRIDE;
+ return NULL;
+}
+#endif
+
+/* -------------------------------------------------------------------- */
+/* collection manager operators */
+
+/**
+ * Recursively get the collection for a given index
+ */
+static SceneCollection *scene_collection_from_index(ListBase *lb, const int number, int *i)
+{
+ for (SceneCollection *sc = lb->first; sc; sc = sc->next) {
+ if (*i == number) {
+ return sc;
+ }
+
+ (*i)++;
+
+ SceneCollection *sc_nested = scene_collection_from_index(&sc->scene_collections, number, i);
+ if (sc_nested) {
+ return sc_nested;
+ }
+ }
+ return NULL;
+}
+
+static int collection_link_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc;
+
+ int scene_collection_index = RNA_enum_get(op->ptr, "scene_collection");
+ if (scene_collection_index == 0) {
+ sc = sc_master;
+ }
+ else {
+ int index = 1;
+ sc = scene_collection_from_index(&sc_master->scene_collections, scene_collection_index, &index);
+ BLI_assert(sc);
+ }
+
+ BKE_collection_link(sl, sc);
+
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+static int collection_link_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ if (BKE_collection_master(CTX_data_scene(C))->scene_collections.first == NULL) {
+ RNA_enum_set(op->ptr, "scene_collection", 0);
+ return collection_link_exec(C, op);
+ }
+ else {
+ return WM_enum_search_invoke(C, op, event);
+ }
+}
+
+static void collection_scene_collection_itemf_recursive(
+ EnumPropertyItem *tmp, EnumPropertyItem **item, int *totitem, int *value, SceneCollection *sc)
+{
+ tmp->value = *value;
+ tmp->icon = ICON_COLLAPSEMENU;
+ tmp->identifier = sc->name;
+ tmp->name = sc->name;
+ RNA_enum_item_add(item, totitem, tmp);
+
+ (*value)++;
+
+ for (SceneCollection *ncs = sc->scene_collections.first; ncs; ncs = ncs->next) {
+ collection_scene_collection_itemf_recursive(tmp, item, totitem, value, ncs);
+ }
+}
+
+static EnumPropertyItem *collection_scene_collection_itemf(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ EnumPropertyItem *item = NULL;
+ int value = 0, totitem = 0;
+
+ Scene *scene = CTX_data_scene(C);
+ SceneCollection *sc = BKE_collection_master(scene);
+
+ collection_scene_collection_itemf_recursive(&tmp, &item, &totitem, &value, sc);
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
+
+void OUTLINER_OT_collection_link(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "OUTLINER_OT_collection_link";
+ ot->description = "Link a new collection to the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_link_exec;
+ ot->invoke = collection_link_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ prop = RNA_def_enum(ot->srna, "scene_collection", DummyRNA_NULL_items, 0, "Scene Collection", "");
+ RNA_def_enum_funcs(prop, collection_scene_collection_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
+}
+
+/**
+ * Returns true if selected element is a collection directly
+ * linked to the active SceneLayer (not a nested collection)
+ */
+static int collection_unlink_poll(bContext *C)
+{
+ LayerCollection *lc = outliner_collection_active(C);
+
+ if (lc == NULL) {
+ return 0;
+ }
+
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ return BLI_findindex(&sl->layer_collections, lc) != -1 ? 1 : 0;
+}
+
+static int collection_unlink_exec(bContext *C, wmOperator *op)
+{
+ LayerCollection *lc = outliner_collection_active(C);
+
+ if (lc == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Active element is not a collection");
+ return OPERATOR_CANCELLED;
+ }
+
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ BKE_collection_unlink(sl, lc);
+
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_unlink(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Collection";
+ ot->idname = "OUTLINER_OT_collection_unlink";
+ ot->description = "Unlink collection from the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_unlink_exec;
+ ot->poll = collection_unlink_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int collection_new_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ SceneCollection *sc = BKE_collection_add(scene, NULL, NULL);
+ BKE_collection_link(sl, sc);
+
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Collection";
+ ot->idname = "OUTLINER_OT_collection_new";
+ ot->description = "Add a new collection to the scene, and link it to the active layer";
+
+ /* api callbacks */
+ ot->exec = collection_new_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/**
+ * Returns true is selected element is a collection
+ */
+static int collection_override_new_poll(bContext *(C))
+{
+#ifdef TODO_LAYER_OVERRIDE
+ /* disable for now, since it's not implemented */
+ (void) C;
+ return 0;
+#else
+ return outliner_collection_active(C) ? 1 : 0;
+#endif
+}
+
+static int collection_override_new_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ TODO_LAYER_OVERRIDE;
+ BKE_report(op->reports, RPT_ERROR, "OUTLINER_OT_collections_override_new not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+/* in the middle of renames remove s */
+void OUTLINER_OT_collection_override_new(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "New Override";
+ ot->idname = "OUTLINER_OT_collection_override_new";
+ ot->description = "Add a new override to the active collection";
+
+ /* api callbacks */
+ ot->invoke = collection_override_new_invoke;
+ ot->poll = collection_override_new_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+struct CollectionDeleteData {
+ Scene *scene;
+ SpaceOops *soops;
+};
+
+static TreeTraversalAction collection_delete_cb(TreeElement *te, void *customdata)
+{
+ struct CollectionDeleteData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+ SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+
+ if (!scene_collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ if (scene_collection == BKE_collection_master(data->scene)) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* XXX removing the treestore element shouldn't be done, it makes us loose information after
+ * undo/file-read. We do need it here however, because non-ID elements don't have an ID pointer
+ * that can be used to lookup the TreeStoreElem when recreating the TreeElement. This index
+ * won't be correct after removing a collection from the list though.
+ * This works as workaround, but having a proper way to find the TreeStoreElem for a recreated
+ * TreeElement would be better. It could use an idname or the directdata pointer for that. */
+ outliner_remove_treestore_element(data->soops, tselem);
+ BKE_collection_remove(data->scene, scene_collection);
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionDeleteData data = {.scene = scene, .soops = soops};
+
+ TODO_LAYER_OVERRIDE; /* handle overrides */
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_delete_cb, &data);
+
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collections_delete(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Delete";
+ ot->idname = "OUTLINER_OT_collections_delete";
+ ot->description = "Delete selected overrides or collections";
+
+ /* api callbacks */
+ ot->exec = collection_delete_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int collection_select_exec(bContext *C, wmOperator *op)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ const int collection_index = RNA_int_get(op->ptr, "collection_index");
+ sl->active_collection = collection_index;
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select";
+ ot->idname = "OUTLINER_OT_collection_select";
+ ot->description = "Change active collection or override";
+
+ /* api callbacks */
+ ot->exec = collection_select_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(ot->srna, "collection_index", 0, 0, INT_MAX, "Index",
+ "Index of collection to select", 0, INT_MAX);
+}
+
+/* -------------------------------------------------------------------- */
+
+static int stubs_invoke(bContext *UNUSED(C), wmOperator *op, const wmEvent *UNUSED(event))
+{
+ TODO_LAYER_OPERATORS;
+ BKE_report(op->reports, RPT_ERROR, "Operator not implemented yet");
+ return OPERATOR_CANCELLED;
+}
+
+void OUTLINER_OT_collection_objects_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_add";
+ ot->description = "Add selected objects to collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Object";
+ ot->idname = "OUTLINER_OT_collection_objects_remove";
+ ot->description = "Remove objects from collection";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_select(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_select";
+ ot->description = "Select collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_objects_deselect(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Objects";
+ ot->idname = "OUTLINER_OT_collection_objects_deselect";
+ ot->description = "Deselect collection objects";
+
+ /* api callbacks */
+ ot->invoke = stubs_invoke;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d15c3d67d45..cbfe0828103 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -67,9 +67,6 @@
#include "WM_api.h"
#include "WM_types.h"
-#include "BIF_gl.h"
-#include "BIF_glutil.h"
-
#include "GPU_immediate.h"
#include "UI_interface.h"
@@ -248,15 +245,13 @@ static void restrictbutton_gp_layer_flag_cb(bContext *C, void *UNUSED(poin), voi
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
}
-static void restrictbutton_collection_hide_cb(bContext *C, void *poin, void *poin2)
+static void restrictbutton_collection_hide_cb(bContext *C, void *poin, void *UNUSED(poin2))
{
Scene *scene = poin;
- LayerCollection *collection = poin2;
- SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection);
/* hide and deselect bases that are directly influenced by this LayerCollection */
- BKE_scene_layer_base_flag_recalculate(sl);
- BKE_scene_layer_engine_settings_collection_recalculate(sl, collection);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
@@ -267,10 +262,9 @@ static void restrictbutton_collection_hide_select_cb(bContext *C, void *poin, vo
LayerCollection *collection = poin2;
if ((collection->flag & COLLECTION_SELECTABLE) == 0) {
- SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, collection);
-
/* deselect bases that are directly influenced by this LayerCollection */
- BKE_scene_layer_base_flag_recalculate(sl);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
}
WM_event_add_notifier(C, NC_SCENE | ND_LAYER_CONTENT, NULL);
@@ -421,6 +415,13 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
}
case TSE_R_LAYER:
break;
+ case TSE_SCENE_COLLECTION:
+ case TSE_LAYER_COLLECTION:
+ {
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
+ BKE_collection_rename(scene, sc, te->name);
+ break;
+ }
}
}
tselem->flag &= ~TSE_TEXTBUT;
@@ -569,7 +570,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS);
}
- else if (tselem->type == TSE_COLLECTION) {
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
LayerCollection *collection = te->directdata;
UI_block_emboss_set(block, UI_EMBOSS_NONE);
@@ -663,18 +664,23 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex)
float miny = v2d->cur.ymin;
if (miny < v2d->tot.ymin) miny = v2d->tot.ymin;
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+ glLineWidth(1.0f);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+
+ immBegin(PRIM_LINES, 4);
+
+ immVertex2f(pos, sizex, v2d->cur.ymax);
+ immVertex2f(pos, sizex, miny);
+
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, v2d->cur.ymax);
+ immVertex2f(pos, sizex + OL_RNA_COL_SIZEX, miny);
- /* draw column separator lines */
- fdrawline((float)sizex,
- v2d->cur.ymax,
- (float)sizex,
- miny);
+ immEnd();
- fdrawline((float)sizex + OL_RNA_COL_SIZEX,
- v2d->cur.ymax,
- (float)sizex + OL_RNA_COL_SIZEX,
- miny);
+ immUnbindProgram();
}
static void outliner_draw_rnabuts(uiBlock *block, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb)
@@ -772,7 +778,7 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon)
/* restrict column clip... it has been coded by simply overdrawing, doesnt work for buttons */
if (arg->x >= arg->xmax) {
glEnable(GL_BLEND);
- UI_icon_draw_aspect(arg->x, arg->y, icon, 1.0f / UI_DPI_FAC, arg->alpha);
+ UI_icon_draw_alpha(arg->x, arg->y, icon, arg->alpha);
glDisable(GL_BLEND);
}
else {
@@ -825,9 +831,6 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
struct DrawIconArg arg;
float aspect;
- /* icons tiny bit away from text */
- x -= 0.15f * UI_UNIT_Y;
-
/* make function calls a bit compacter */
arg.block = block;
arg.id = tselem->id;
@@ -835,189 +838,261 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
arg.xb = x; /* for ui buttons */
arg.yb = y;
arg.alpha = alpha;
-
+
/* placement of icons, copied from interface_widgets.c */
aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
- arg.x = x = x + 4.0f * aspect;
- arg.y = y = y + 0.1f * UI_UNIT_Y;
+ x += 2.0f * aspect;
+ y += 2.0f * aspect;
+ arg.x = x;
+ arg.y = y;
+
+#define ICON_DRAW(_icon) UI_icon_draw_alpha(x, y, _icon, alpha)
if (tselem->type) {
switch (tselem->type) {
case TSE_ANIM_DATA:
- UI_icon_draw(x, y, ICON_ANIM_DATA); break; // xxx
+ ICON_DRAW(ICON_ANIM_DATA); /* XXX */
+ break;
case TSE_NLA:
- UI_icon_draw(x, y, ICON_NLA); break;
+ ICON_DRAW(ICON_NLA);
+ break;
case TSE_NLA_TRACK:
- UI_icon_draw(x, y, ICON_NLA); break; // XXX
+ ICON_DRAW(ICON_NLA); /* XXX */
+ break;
case TSE_NLA_ACTION:
- UI_icon_draw(x, y, ICON_ACTION); break;
+ ICON_DRAW(ICON_ACTION);
+ break;
case TSE_DRIVER_BASE:
- UI_icon_draw(x, y, ICON_DRIVER); break;
+ ICON_DRAW(ICON_DRIVER);
+ break;
case TSE_DEFGROUP_BASE:
- UI_icon_draw(x, y, ICON_GROUP_VERTEX); break;
+ ICON_DRAW(ICON_GROUP_VERTEX);
+ break;
case TSE_BONE:
case TSE_EBONE:
- UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ ICON_DRAW(ICON_BONE_DATA);
+ break;
case TSE_CONSTRAINT_BASE:
- UI_icon_draw(x, y, ICON_CONSTRAINT); break;
+ ICON_DRAW(ICON_CONSTRAINT);
+ break;
case TSE_MODIFIER_BASE:
- UI_icon_draw(x, y, ICON_MODIFIER); break;
+ ICON_DRAW(ICON_MODIFIER);
+ break;
case TSE_LINKED_OB:
- UI_icon_draw(x, y, ICON_OBJECT_DATA); break;
+ ICON_DRAW(ICON_OBJECT_DATA);
+ break;
case TSE_LINKED_PSYS:
- UI_icon_draw(x, y, ICON_PARTICLES); break;
+ ICON_DRAW(ICON_PARTICLES);
+ break;
case TSE_MODIFIER:
{
Object *ob = (Object *)tselem->id;
ModifierData *md = BLI_findlink(&ob->modifiers, tselem->nr);
switch ((ModifierType)md->type) {
- case eModifierType_Subsurf:
- UI_icon_draw(x, y, ICON_MOD_SUBSURF); break;
- case eModifierType_Armature:
- UI_icon_draw(x, y, ICON_MOD_ARMATURE); break;
- case eModifierType_Lattice:
- UI_icon_draw(x, y, ICON_MOD_LATTICE); break;
- case eModifierType_Curve:
- UI_icon_draw(x, y, ICON_MOD_CURVE); break;
- case eModifierType_Build:
- UI_icon_draw(x, y, ICON_MOD_BUILD); break;
- case eModifierType_Mirror:
- UI_icon_draw(x, y, ICON_MOD_MIRROR); break;
- case eModifierType_Decimate:
- UI_icon_draw(x, y, ICON_MOD_DECIM); break;
- case eModifierType_Wave:
- UI_icon_draw(x, y, ICON_MOD_WAVE); break;
- case eModifierType_Hook:
- UI_icon_draw(x, y, ICON_HOOK); break;
- case eModifierType_Softbody:
- UI_icon_draw(x, y, ICON_MOD_SOFT); break;
- case eModifierType_Boolean:
- UI_icon_draw(x, y, ICON_MOD_BOOLEAN); break;
- case eModifierType_ParticleSystem:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
+ case eModifierType_Subsurf:
+ ICON_DRAW(ICON_MOD_SUBSURF);
+ break;
+ case eModifierType_Armature:
+ ICON_DRAW(ICON_MOD_ARMATURE);
+ break;
+ case eModifierType_Lattice:
+ ICON_DRAW(ICON_MOD_LATTICE);
+ break;
+ case eModifierType_Curve:
+ ICON_DRAW(ICON_MOD_CURVE);
+ break;
+ case eModifierType_Build:
+ ICON_DRAW(ICON_MOD_BUILD);
+ break;
+ case eModifierType_Mirror:
+ ICON_DRAW(ICON_MOD_MIRROR);
+ break;
+ case eModifierType_Decimate:
+ ICON_DRAW(ICON_MOD_DECIM);
+ break;
+ case eModifierType_Wave:
+ ICON_DRAW(ICON_MOD_WAVE);
+ break;
+ case eModifierType_Hook:
+ ICON_DRAW(ICON_HOOK);
+ break;
+ case eModifierType_Softbody:
+ ICON_DRAW(ICON_MOD_SOFT);
+ break;
+ case eModifierType_Boolean:
+ ICON_DRAW(ICON_MOD_BOOLEAN);
+ break;
+ case eModifierType_ParticleSystem:
+ ICON_DRAW(ICON_MOD_PARTICLES);
+ break;
case eModifierType_ParticleInstance:
- UI_icon_draw(x, y, ICON_MOD_PARTICLES); break;
+ ICON_DRAW(ICON_MOD_PARTICLES);
+ break;
case eModifierType_EdgeSplit:
- UI_icon_draw(x, y, ICON_MOD_EDGESPLIT); break;
+ ICON_DRAW(ICON_MOD_EDGESPLIT);
+ break;
case eModifierType_Array:
- UI_icon_draw(x, y, ICON_MOD_ARRAY); break;
+ ICON_DRAW(ICON_MOD_ARRAY);
+ break;
case eModifierType_UVProject:
case eModifierType_UVWarp: /* TODO, get own icon */
- UI_icon_draw(x, y, ICON_MOD_UVPROJECT); break;
+ ICON_DRAW(ICON_MOD_UVPROJECT);
+ break;
case eModifierType_Displace:
- UI_icon_draw(x, y, ICON_MOD_DISPLACE); break;
+ ICON_DRAW(ICON_MOD_DISPLACE);
+ break;
case eModifierType_Shrinkwrap:
- UI_icon_draw(x, y, ICON_MOD_SHRINKWRAP); break;
+ ICON_DRAW(ICON_MOD_SHRINKWRAP);
+ break;
case eModifierType_Cast:
- UI_icon_draw(x, y, ICON_MOD_CAST); break;
+ ICON_DRAW(ICON_MOD_CAST);
+ break;
case eModifierType_MeshDeform:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break;
+ case eModifierType_SurfaceDeform:
+ ICON_DRAW(ICON_MOD_MESHDEFORM);
+ break;
case eModifierType_Bevel:
- UI_icon_draw(x, y, ICON_MOD_BEVEL); break;
+ ICON_DRAW(ICON_MOD_BEVEL);
+ break;
case eModifierType_Smooth:
case eModifierType_LaplacianSmooth:
case eModifierType_CorrectiveSmooth:
- UI_icon_draw(x, y, ICON_MOD_SMOOTH); break;
+ ICON_DRAW(ICON_MOD_SMOOTH);
+ break;
case eModifierType_SimpleDeform:
- UI_icon_draw(x, y, ICON_MOD_SIMPLEDEFORM); break;
+ ICON_DRAW(ICON_MOD_SIMPLEDEFORM);
+ break;
case eModifierType_Mask:
- UI_icon_draw(x, y, ICON_MOD_MASK); break;
+ ICON_DRAW(ICON_MOD_MASK);
+ break;
case eModifierType_Cloth:
- UI_icon_draw(x, y, ICON_MOD_CLOTH); break;
+ ICON_DRAW(ICON_MOD_CLOTH);
+ break;
case eModifierType_Explode:
- UI_icon_draw(x, y, ICON_MOD_EXPLODE); break;
+ ICON_DRAW(ICON_MOD_EXPLODE);
+ break;
case eModifierType_Collision:
case eModifierType_Surface:
- UI_icon_draw(x, y, ICON_MOD_PHYSICS); break;
+ ICON_DRAW(ICON_MOD_PHYSICS);
+ break;
case eModifierType_Fluidsim:
- UI_icon_draw(x, y, ICON_MOD_FLUIDSIM); break;
+ ICON_DRAW(ICON_MOD_FLUIDSIM);
+ break;
case eModifierType_Multires:
- UI_icon_draw(x, y, ICON_MOD_MULTIRES); break;
+ ICON_DRAW(ICON_MOD_MULTIRES);
+ break;
case eModifierType_Smoke:
- UI_icon_draw(x, y, ICON_MOD_SMOKE); break;
+ ICON_DRAW(ICON_MOD_SMOKE);
+ break;
case eModifierType_Solidify:
- UI_icon_draw(x, y, ICON_MOD_SOLIDIFY); break;
+ ICON_DRAW(ICON_MOD_SOLIDIFY);
+ break;
case eModifierType_Screw:
- UI_icon_draw(x, y, ICON_MOD_SCREW); break;
+ ICON_DRAW(ICON_MOD_SCREW);
+ break;
case eModifierType_Remesh:
- UI_icon_draw(x, y, ICON_MOD_REMESH); break;
+ ICON_DRAW(ICON_MOD_REMESH);
+ break;
case eModifierType_WeightVGEdit:
case eModifierType_WeightVGMix:
case eModifierType_WeightVGProximity:
- UI_icon_draw(x, y, ICON_MOD_VERTEX_WEIGHT); break;
+ ICON_DRAW(ICON_MOD_VERTEX_WEIGHT);
+ break;
case eModifierType_DynamicPaint:
- UI_icon_draw(x, y, ICON_MOD_DYNAMICPAINT); break;
+ ICON_DRAW(ICON_MOD_DYNAMICPAINT);
+ break;
case eModifierType_Ocean:
- UI_icon_draw(x, y, ICON_MOD_OCEAN); break;
+ ICON_DRAW(ICON_MOD_OCEAN);
+ break;
case eModifierType_Warp:
- UI_icon_draw(x, y, ICON_MOD_WARP); break;
+ ICON_DRAW(ICON_MOD_WARP);
+ break;
case eModifierType_Skin:
- UI_icon_draw(x, y, ICON_MOD_SKIN); break;
+ ICON_DRAW(ICON_MOD_SKIN);
+ break;
case eModifierType_Triangulate:
- UI_icon_draw(x, y, ICON_MOD_TRIANGULATE); break;
+ ICON_DRAW(ICON_MOD_TRIANGULATE);
+ break;
case eModifierType_MeshCache:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_MeshSequenceCache:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_Wireframe:
- UI_icon_draw(x, y, ICON_MOD_WIREFRAME); break;
+ ICON_DRAW(ICON_MOD_WIREFRAME);
+ break;
case eModifierType_LaplacianDeform:
- UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */
+ ICON_DRAW(ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ break;
case eModifierType_DataTransfer:
- UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break;
+ ICON_DRAW(ICON_MOD_DATA_TRANSFER);
+ break;
case eModifierType_NormalEdit:
- UI_icon_draw(x, y, ICON_MOD_NORMALEDIT); break;
+ ICON_DRAW(ICON_MOD_NORMALEDIT);
+ break;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
case NUM_MODIFIER_TYPES:
- UI_icon_draw(x, y, ICON_DOT); break;
+ ICON_DRAW(ICON_DOT);
+ break;
}
break;
}
case TSE_POSE_BASE:
- UI_icon_draw(x, y, ICON_ARMATURE_DATA); break;
+ ICON_DRAW(ICON_ARMATURE_DATA);
+ break;
case TSE_POSE_CHANNEL:
- UI_icon_draw(x, y, ICON_BONE_DATA); break;
+ ICON_DRAW(ICON_BONE_DATA);
+ break;
case TSE_PROXY:
- UI_icon_draw(x, y, ICON_GHOST); break;
+ ICON_DRAW(ICON_GHOST);
+ break;
case TSE_R_LAYER_BASE:
- UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
+ ICON_DRAW(ICON_RENDERLAYERS);
+ break;
case TSE_R_LAYER:
- UI_icon_draw(x, y, ICON_RENDERLAYERS); break;
+ ICON_DRAW(ICON_RENDERLAYERS);
+ break;
case TSE_LINKED_LAMP:
- UI_icon_draw(x, y, ICON_LAMP_DATA); break;
+ ICON_DRAW(ICON_LAMP_DATA);
+ break;
case TSE_LINKED_MAT:
- UI_icon_draw(x, y, ICON_MATERIAL_DATA); break;
+ ICON_DRAW(ICON_MATERIAL_DATA);
+ break;
case TSE_POSEGRP_BASE:
- UI_icon_draw(x, y, ICON_GROUP_BONE); break;
+ ICON_DRAW(ICON_GROUP_BONE);
+ break;
case TSE_SEQUENCE:
if (te->idcode == SEQ_TYPE_MOVIE)
- UI_icon_draw(x, y, ICON_SEQUENCE);
+ ICON_DRAW(ICON_SEQUENCE);
else if (te->idcode == SEQ_TYPE_META)
- UI_icon_draw(x, y, ICON_DOT);
+ ICON_DRAW(ICON_DOT);
else if (te->idcode == SEQ_TYPE_SCENE)
- UI_icon_draw(x, y, ICON_SCENE);
+ ICON_DRAW(ICON_SCENE);
else if (te->idcode == SEQ_TYPE_SOUND_RAM)
- UI_icon_draw(x, y, ICON_SOUND);
+ ICON_DRAW(ICON_SOUND);
else if (te->idcode == SEQ_TYPE_IMAGE)
- UI_icon_draw(x, y, ICON_IMAGE_COL);
+ ICON_DRAW(ICON_IMAGE_COL);
else
- UI_icon_draw(x, y, ICON_PARTICLES);
+ ICON_DRAW(ICON_PARTICLES);
break;
case TSE_SEQ_STRIP:
- UI_icon_draw(x, y, ICON_LIBRARY_DATA_DIRECT);
+ ICON_DRAW(ICON_LIBRARY_DATA_DIRECT);
break;
case TSE_SEQUENCE_DUP:
- UI_icon_draw(x, y, ICON_OBJECT_DATA);
+ ICON_DRAW(ICON_OBJECT_DATA);
break;
case TSE_RNA_STRUCT:
if (RNA_struct_is_ID(te->rnaptr.type)) {
arg.id = (ID *)te->rnaptr.data;
tselem_draw_icon_uibut(&arg, RNA_struct_ui_icon(te->rnaptr.type));
}
- else
- UI_icon_draw(x, y, RNA_struct_ui_icon(te->rnaptr.type));
+ else {
+ int icon = RNA_struct_ui_icon(te->rnaptr.type);
+ ICON_DRAW(icon);
+ }
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
#if 0
@@ -1026,7 +1101,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
break;
#endif
default:
- UI_icon_draw(x, y, ICON_DOT); break;
+ ICON_DRAW(ICON_DOT);
+ break;
}
}
else if (tselem->id) {
@@ -1131,17 +1207,18 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
}
}
+
+#undef ICON_DRAW
}
-static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, SpaceOops *soops, ListBase *lb, int level,
- int xmax, int *offsx, int ys)
+static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SceneLayer *sl, SpaceOops *soops,
+ ListBase *lb, int level, int xmax, int *offsx, int ys, float alpha_fac)
{
TreeElement *te;
TreeStoreElem *tselem;
eOLDrawState active;
for (te = lb->first; te; te = te->next) {
-
/* exit drawing early */
if ((*offsx) - UI_UNIT_X > xmax)
break;
@@ -1164,25 +1241,27 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Sce
}
}
else {
- active = tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false);
+ active = tree_element_type_active(C, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false);
}
if (active != OL_DRAWSEL_NONE) {
float ufac = UI_UNIT_X / 20.0f;
+ float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
UI_draw_roundbox_corner_set(UI_CNR_ALL);
- float color[4] = {1.0f, 1.0f, 1.0f, 0.4f};
+ color[3] *= alpha_fac;
+
UI_draw_roundbox(
- (float) *offsx - 1.0f * ufac,
+ (float) *offsx + 1.0f * ufac,
(float)ys + 1.0f * ufac,
- (float)*offsx + UI_UNIT_X - 2.0f * ufac,
+ (float)*offsx + UI_UNIT_X - 1.0f * ufac,
(float)ys + UI_UNIT_Y - ufac,
(float)UI_UNIT_Y / 2.0f - ufac,
color);
glEnable(GL_BLEND); /* roundbox disables */
}
- tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f);
+ tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f * alpha_fac);
te->xs = *offsx;
te->ys = ys;
te->xend = (short)*offsx + UI_UNIT_X;
@@ -1193,7 +1272,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Sce
/* this tree element always has same amount of branches, so don't draw */
if (tselem->type != TSE_R_LAYER)
- outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, level + 1, xmax, offsx, ys);
+ outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
}
}
@@ -1217,10 +1296,10 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
static void outliner_draw_tree_element(
- bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, SceneLayer *sl, ARegion *ar, SpaceOops *soops,
- TreeElement *te, int startx, int *starty, TreeElement **te_edit)
+ bContext *C, uiBlock *block, const uiFontStyle *fstyle, Scene *scene, SceneLayer *sl,
+ ARegion *ar, SpaceOops *soops, TreeElement *te, bool draw_grayed_out,
+ int startx, int *starty, TreeElement **te_edit, TreeElement **te_floating)
{
- TreeElement *ten;
TreeStoreElem *tselem;
float ufac = UI_UNIT_X / 20.0f;
int offsx = 0;
@@ -1229,12 +1308,16 @@ static void outliner_draw_tree_element(
tselem = TREESTORE(te);
if (*starty + 2 * UI_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) {
+ const float alpha_fac = draw_grayed_out ? 0.5f : 1.0f;
+ const float alpha = 0.5f * alpha_fac;
int xmax = ar->v2d.cur.xmax;
- float alpha = 0.5f;
-
+
if ((tselem->flag & TSE_TEXTBUT) && (*te_edit == NULL)) {
*te_edit = te;
}
+ if ((te->drag_data != NULL) && (*te_floating == NULL)) {
+ *te_floating = te;
+ }
/* icons can be ui buts, we don't want it to overlap with restrict */
if ((soops->flag & SO_HIDE_RESTRICTCOLS) == 0)
@@ -1287,9 +1370,7 @@ static void outliner_draw_tree_element(
}
}
else {
- if (tree_element_type_active(NULL, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false) != OL_DRAWSEL_NONE) {
- active = OL_DRAWSEL_ACTIVE;
- }
+ active = tree_element_type_active(C, scene, sl, soops, te, tselem, OL_SETSEL_NONE, false);
rgba_float_args_set(color, 0.85f, 0.85f, 1.0f, alpha);
}
@@ -1297,9 +1378,9 @@ static void outliner_draw_tree_element(
if (active != OL_DRAWSEL_NONE) {
UI_draw_roundbox_corner_set(UI_CNR_ALL);
UI_draw_roundbox(
- (float)startx + UI_UNIT_X,
+ (float)startx + UI_UNIT_X + 1.0f * ufac,
(float)*starty + 1.0f * ufac,
- (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac,
+ (float)startx + 2.0f * UI_UNIT_X - 1.0f * ufac,
(float)*starty + UI_UNIT_Y - 1.0f * ufac,
UI_UNIT_Y / 2.0f - 1.0f * ufac, color);
glEnable(GL_BLEND); /* roundbox disables it */
@@ -1314,39 +1395,40 @@ static void outliner_draw_tree_element(
icon_x = startx;
else
icon_x = startx + 5 * ufac;
-
+
// icons a bit higher
if (TSELEM_OPEN(tselem, soops))
- UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN);
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_DOWN,
+ alpha_fac);
else
- UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT);
+ UI_icon_draw_alpha((float)icon_x + 2 * ufac, (float)*starty + 1 * ufac, ICON_DISCLOSURE_TRI_RIGHT,
+ alpha_fac);
}
offsx += UI_UNIT_X;
/* datatype icon */
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
-
- tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, 1.0f);
-
- offsx += UI_UNIT_X;
+ tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac);
+ offsx += UI_UNIT_X + 2 * ufac;
}
else
offsx += 2 * ufac;
if (tselem->type == 0 && ID_IS_LINKED_DATABLOCK(tselem->id)) {
- glPixelTransferf(GL_ALPHA_SCALE, 0.5f);
if (tselem->id->tag & LIB_TAG_MISSING) {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN,
+ alpha_fac);
}
else if (tselem->id->tag & LIB_TAG_INDIRECT) {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_INDIRECT,
+ alpha_fac);
}
else {
- UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT);
+ UI_icon_draw_alpha((float)startx + offsx + 2 * ufac, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT,
+ alpha_fac);
}
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
- offsx += UI_UNIT_X;
+ offsx += UI_UNIT_X + 2 * ufac;
}
glDisable(GL_BLEND);
@@ -1364,6 +1446,7 @@ static void outliner_draw_tree_element(
else {
UI_GetThemeColor4ubv(TH_TEXT, text_col);
}
+ text_col[3] *= alpha_fac;
UI_fontstyle_draw_simple(fstyle, startx + offsx, *starty + 5 * ufac, te->name, text_col);
}
@@ -1376,31 +1459,33 @@ static void outliner_draw_tree_element(
if (tselem->type == 0 && te->idcode == ID_SCE) {
/* pass */
}
+ /* this tree element always has same amount of branches, so don't draw */
else if (tselem->type != TSE_R_LAYER) {
- /* this tree element always has same amount of branches, so don't draw */
-
int tempx = startx + offsx;
-
+
+ glEnable(GL_BLEND);
+
/* divider */
{
VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
unsigned char col[4];
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
+ col[3] *= alpha_fac;
+
immUniformColor4ubv(col);
immRecti(pos, tempx - 10.0f * ufac,
- *starty + 4.0f * ufac,
- tempx - 8.0f * ufac,
- *starty + UI_UNIT_Y - 4.0f * ufac);
+ *starty + 4.0f * ufac,
+ tempx - 8.0f * ufac,
+ *starty + UI_UNIT_Y - 4.0f * ufac);
immUnbindProgram();
}
- glEnable(GL_BLEND);
- glPixelTransferf(GL_ALPHA_SCALE, 0.5);
-
- outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, 0, xmax, &tempx, *starty);
-
- glPixelTransferf(GL_ALPHA_SCALE, 1.0);
+
+ outliner_draw_iconrow(C, block, scene, sl, soops, &te->subtree, 0, xmax, &tempx,
+ *starty, alpha_fac);
+
glDisable(GL_BLEND);
}
}
@@ -1410,16 +1495,20 @@ static void outliner_draw_tree_element(
te->xs = startx;
te->ys = *starty;
te->xend = startx + offsx;
-
+
if (TSELEM_OPEN(tselem, soops)) {
*starty -= UI_UNIT_Y;
- for (ten = te->subtree.first; ten; ten = ten->next) {
- outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, ten, startx + UI_UNIT_X, starty, te_edit);
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ /* check if element needs to be drawn grayed out, but also gray out
+ * childs of a grayed out parent (pass on draw_grayed_out to childs) */
+ bool draw_childs_grayed_out = draw_grayed_out || (ten->drag_data != NULL);
+ outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, ten, draw_childs_grayed_out,
+ startx + UI_UNIT_X, starty, te_edit, te_floating);
}
}
else {
- for (ten = te->subtree.first; ten; ten = ten->next) {
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
outliner_set_coord_tree_element(ten, startx, *starty);
}
@@ -1427,19 +1516,74 @@ static void outliner_draw_tree_element(
}
}
-static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx, int *starty)
+static void outliner_draw_tree_element_floating(
+ const ARegion *ar, const TreeElement *te_floating)
{
- if (BLI_listbase_is_empty(lb)) return;
+ const TreeElement *te_insert = te_floating->drag_data->insert_handle;
+ const int line_width = 2;
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ int coord_y = te_insert->ys;
+ int coord_x = te_insert->xs;
+ unsigned char col[4];
+
+ if (te_insert == te_floating) {
+ /* don't draw anything */
+ return;
+ }
+
+ UI_GetThemeColorShade4ubv(TH_BACK, -40, col);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ glEnable(GL_BLEND);
+ if (ELEM(te_floating->drag_data->insert_type, TE_INSERT_BEFORE, TE_INSERT_AFTER)) {
+ if (te_floating->drag_data->insert_type == TE_INSERT_BEFORE) {
+ coord_y += UI_UNIT_Y;
+ }
+ immUniformColor4ubv(col);
+ glLineWidth(line_width);
+
+ immBegin(PRIM_LINE_STRIP, 2);
+ immVertex2f(pos, coord_x, coord_y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y);
+ immEnd();
+ }
+ else {
+ BLI_assert(te_floating->drag_data->insert_type == TE_INSERT_INTO);
+ immUniformColor4ub(UNPACK3(col), col[3] * 0.5f);
+
+ immBegin(PRIM_QUADS, 4);
+ immVertex2f(pos, coord_x, coord_y);
+ immVertex2f(pos, coord_x, coord_y + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, coord_y);
+ immEnd();
+ }
+
+ glDisable(GL_BLEND);
+ immUnbindProgram();
+}
+
+static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soops, ListBase *lb, int startx,
+ const unsigned char col[4], bool draw_grayed_out,
+ int *starty)
+{
TreeElement *te;
TreeStoreElem *tselem;
int y1, y2;
+ if (BLI_listbase_is_empty(lb)) {
+ return;
+ }
+
y1 = y2 = *starty; /* for vertical lines between objects */
for (te = lb->first; te; te = te->next) {
+ bool draw_childs_grayed_out = draw_grayed_out || (te->drag_data != NULL);
y2 = *starty;
tselem = TREESTORE(te);
-
+
+ immUniformColor4ub(UNPACK3(col), col[3] * (draw_childs_grayed_out ? 0.5f : 1.0f));
+
/* horizontal line? */
if (tselem->type == 0 && (te->idcode == ID_OB || te->idcode == ID_SCE))
immRecti(pos, startx, *starty, startx + UI_UNIT_X, *starty - 1);
@@ -1447,9 +1591,12 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
*starty -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops))
- outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X, starty);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, &te->subtree, startx + UI_UNIT_X,
+ col, draw_childs_grayed_out, starty);
}
-
+
+ immUniformColor4ub(UNPACK3(col), col[3] * (draw_grayed_out ? 0.5f : 1.0f));
+
/* vertical line */
te = lb->last;
if (te->parent || lb->first != lb->last) {
@@ -1462,12 +1609,17 @@ static void outliner_draw_hierarchy_lines_recursive(unsigned pos, SpaceOops *soo
static void outliner_draw_hierarchy_lines(SpaceOops *soops, ListBase *lb, int startx, int *starty)
{
VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ unsigned char col[4];
+
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- unsigned char col[3];
UI_GetThemeColorBlend3ubv(TH_BACK, TH_TEXT, 0.4f, col);
- immUniformColor3ubv(col);
- outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, starty);
+ col[3] = 255;
+
+ glEnable(GL_BLEND);
+ outliner_draw_hierarchy_lines_recursive(pos, soops, lb, startx, col, false, starty);
+ glDisable(GL_BLEND);
+
immUnbindProgram();
}
@@ -1498,7 +1650,12 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase *
unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immThemeColorShadeAlpha(TH_BACK, -15, -200);
- imm_draw_line(pos, 0, (float)*starty + UI_UNIT_Y, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, 0, (float)*starty + UI_UNIT_Y);
+ immVertex2f(pos, ar->v2d.cur.xmax, (float)*starty + UI_UNIT_Y);
+ immEnd();
+
immUnbindProgram();
}
}
@@ -1532,7 +1689,7 @@ static void outliner_draw_highlights_recursive(
}
/* mouse hover highlights */
- if (tselem->flag & TSE_HIGHLIGHTED) {
+ if ((tselem->flag & TSE_HIGHLIGHTED) || (te->drag_data != NULL)) {
immUniformColor4fv(col_highlight);
immRecti(pos, 0, start_y + 1, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y - 1);
}
@@ -1540,8 +1697,8 @@ static void outliner_draw_highlights_recursive(
*io_start_y -= UI_UNIT_Y;
if (TSELEM_OPEN(tselem, soops)) {
outliner_draw_highlights_recursive(
- pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
- start_x + UI_UNIT_X, io_start_y);
+ pos, ar, soops, &te->subtree, col_selection, col_highlight, col_searchmatch,
+ start_x + UI_UNIT_X, io_start_y);
}
}
}
@@ -1561,7 +1718,7 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOops *soops, int startx,
unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
outliner_draw_highlights_recursive(pos, ar, soops, &soops->tree, col_selection, col_highlight, col_searchmatch,
- startx, starty);
+ startx, starty);
immUnbindProgram();
glDisable(GL_BLEND);
}
@@ -1572,6 +1729,7 @@ static void outliner_draw_tree(
TreeElement **te_edit)
{
const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
+ TreeElement *te_floating = NULL;
int starty, startx;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only once
@@ -1607,7 +1765,11 @@ static void outliner_draw_tree(
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
startx = 0;
for (TreeElement *te = soops->tree.first; te; te = te->next) {
- outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, te, startx, &starty, te_edit);
+ outliner_draw_tree_element(C, block, fstyle, scene, sl, ar, soops, te, te->drag_data != NULL,
+ startx, &starty, te_edit, &te_floating);
+ }
+ if (te_floating && te_floating->drag_data->insert_handle) {
+ outliner_draw_tree_element_floating(ar, te_floating);
}
if (has_restrict_icons) {
@@ -1651,25 +1813,27 @@ static void outliner_back(ARegion *ar)
static void outliner_draw_restrictcols(ARegion *ar)
{
- UI_ThemeColorShadeAlpha(TH_BACK, -15, -200);
+ glLineWidth(1.0f);
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShadeAlpha(TH_BACK, -15, -200);
+ immBegin(PRIM_LINES, 6);
/* view */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)ar->v2d.cur.ymin);
/* render */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)ar->v2d.cur.ymin);
/* render */
- sdrawline((int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- (int)ar->v2d.cur.ymax,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX),
- (int)ar->v2d.cur.ymin);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymax);
+ immVertex2i(pos, (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)ar->v2d.cur.ymin);
+
+ immEnd();
+ immUnbindProgram();
}
/* ****************************************************** */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 0afaf298264..6a3e53281da 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -149,55 +149,6 @@ TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2]
return NULL;
}
-/**
- * Try to find an item under y-coordinate \a view_co_y (view-space).
- * \note Recursive
- */
-TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y)
-{
- for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
- if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
- if (view_co_y > te_iter->ys) {
- /* co_y is inside this element */
- return te_iter;
- }
- else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
- /* co_y is lower than current element, possibly inside children */
- TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
- if (te_sub) {
- return te_sub;
- }
- }
- }
- }
-
- return NULL;
-}
-
-/**
- * Collapsed items can show their children as click-able icons. This function tries to find
- * such an icon that represents the child item at x-coordinate \a view_co_x (view-space).
- *
- * \return a hovered child item or \a parent_te (if no hovered child found).
- */
-TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x)
-{
- if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { /* if parent_te is opened, it doesn't show childs in row */
- /* no recursion, items can only display their direct children in the row */
- for (TreeElement *child_te = parent_te->subtree.first;
- child_te && view_co_x >= child_te->xs; /* don't look further if co_x is smaller than child position*/
- child_te = child_te->next)
- {
- if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) {
- return child_te;
- }
- }
- }
-
- /* return parent if no child is hovered */
- return (TreeElement *)parent_te;
-}
-
/* ************************************************************** */
@@ -304,8 +255,11 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
/* Rename --------------------------------------------------- */
-static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem, ReportList *reports)
+static void do_item_rename(const Scene *scene, ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
+ ReportList *reports)
{
+ bool add_textbut = false;
+
/* can't rename rna datablocks entries or listbases */
if (ELEM(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE)) {
/* do nothing */;
@@ -318,6 +272,18 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
else if (ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) {
BKE_report(reports, RPT_WARNING, "Cannot edit sequence name");
}
+ else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ SceneCollection *master = BKE_collection_master(scene);
+
+ if ((tselem->type == TSE_SCENE_COLLECTION && te->directdata == master) ||
+ (((LayerCollection *)te->directdata)->scene_collection == master))
+ {
+ BKE_report(reports, RPT_WARNING, "Cannot edit name of master collection");
+ }
+ else {
+ add_textbut = true;
+ }
+ }
else if (ID_IS_LINKED_DATABLOCK(tselem->id)) {
BKE_report(reports, RPT_WARNING, "Cannot edit external libdata");
}
@@ -325,34 +291,39 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
BKE_report(reports, RPT_WARNING, "Cannot edit the path of an indirectly linked library");
}
else {
+ add_textbut = true;
+ }
+
+ if (add_textbut) {
tselem->flag |= TSE_TEXTBUT;
ED_region_tag_redraw(ar);
}
}
void item_rename_cb(
- bContext *C, ReportList *reports, Scene *UNUSED(scene), TreeElement *te,
+ bContext *C, ReportList *reports, Scene *scene, TreeElement *te,
TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data))
{
ARegion *ar = CTX_wm_region(C);
- do_item_rename(ar, te, tselem, reports);
+ do_item_rename(scene, ar, te, tselem, reports);
}
-static int do_outliner_item_rename(ReportList *reports, ARegion *ar, TreeElement *te, const float mval[2])
+static int do_outliner_item_rename(const Scene *scene, ReportList *reports, ARegion *ar, TreeElement *te,
+ const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
- do_item_rename(ar, te, tselem, reports);
+ do_item_rename(scene, ar, te, tselem, reports);
return 1;
}
return 0;
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(reports, ar, te, mval)) return 1;
+ if (do_outliner_item_rename(scene, reports, ar, te, mval)) return 1;
}
return 0;
}
@@ -368,7 +339,7 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
+ if (do_outliner_item_rename(CTX_data_scene(C), op->reports, ar, te, fmval)) {
changed = true;
break;
}
@@ -397,9 +368,12 @@ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeSto
ID *id = tselem->id;
BLI_assert(te->idcode != 0 && id != NULL);
- BLI_assert(te->idcode != ID_LI || ((Library *)id)->parent == NULL);
UNUSED_VARS_NDEBUG(te);
+ if (te->idcode == ID_LI && ((Library *)id)->parent != NULL) {
+ BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked library '%s'", id->name);
+ return;
+ }
if (id->tag & LIB_TAG_INDIRECT) {
BKE_reportf(reports, RPT_WARNING, "Cannot delete indirectly linked id '%s'", id->name);
return;
@@ -604,7 +578,8 @@ void OUTLINER_OT_id_remap(wmOperatorType *ot)
ot->flag = 0;
- RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
+ prop = RNA_def_enum(ot->srna, "id_type", rna_enum_id_type_items, ID_OB, "ID Type", "");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
prop = RNA_def_enum(ot->srna, "old_id", DummyRNA_NULL_items, 0, "Old ID", "Old ID to replace");
RNA_def_property_enum_funcs_runtime(prop, NULL, NULL, outliner_id_itemf);
@@ -848,7 +823,7 @@ bool outliner_set_flag(ListBase *lb, short flag, short set)
changed = true;
}
}
- else if (!has_flag){
+ else if (!has_flag) {
tselem->flag |= flag;
changed = true;
}
@@ -1945,6 +1920,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Main *bmain = CTX_data_main(C);
Scene *scene = NULL;
TreeElement *te = NULL;
+ TreeStoreElem *tselem;
char childname[MAX_ID_NAME];
char parname[MAX_ID_NAME];
int partype = 0;
@@ -1954,8 +1930,21 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* Find object hovered over */
te = outliner_dropzone_find(soops, fmval, true);
+ tselem = te ? TREESTORE(te) : NULL;
- if (te) {
+ if (tselem && ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(te);
+
+ scene = BKE_scene_find_from_collection(bmain, sc);
+ BLI_assert(scene);
+ RNA_string_get(op->ptr, "child", childname);
+ ob = (Object *)BKE_libblock_find_name(ID_OB, childname);
+ BKE_collection_object_add(scene, sc, ob);
+
+ DAG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (te) {
RNA_string_set(op->ptr, "parent", te->name);
/* Identify parent and child */
RNA_string_get(op->ptr, "child", childname);
@@ -1998,74 +1987,62 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
wmOperatorType *ot = WM_operatortype_find("OUTLINER_OT_parent_drop", false);
uiPopupMenu *pup = UI_popup_menu_begin(C, IFACE_("Set Parent To"), ICON_NONE);
uiLayout *layout = UI_popup_menu_layout(pup);
-
PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
+ /* Cannot use uiItemEnumO()... have multiple properties to set. */
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_OBJECT);
- /* Cannot use uiItemEnumO()... have multiple properties to set. */
- uiItemFullO_ptr(layout, ot, IFACE_("Object"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
+
/* par becomes parent, make the associated menus */
if (par->type == OB_ARMATURE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE);
- uiItemFullO_ptr(layout, ot, IFACE_("Armature Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_NAME);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Empty Groups"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_ENVELOPE);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Envelope Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_ARMATURE_AUTO);
- uiItemFullO_ptr(layout, ot, IFACE_(" With Automatic Weights"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Bone"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_BONE);
- uiItemFullO_ptr(layout, ot, IFACE_("Bone"),
- 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
else if (par->type == OB_CURVE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_CURVE);
- uiItemFullO_ptr(layout, ot, IFACE_("Curve Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_FOLLOW);
- uiItemFullO_ptr(layout, ot, IFACE_("Follow Path"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
-
- WM_operator_properties_create_ptr(&ptr, ot);
+
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_PATH_CONST);
- uiItemFullO_ptr(layout, ot, IFACE_("Path Constraint"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
else if (par->type == OB_LATTICE) {
- WM_operator_properties_create_ptr(&ptr, ot);
+ ptr = uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS);
RNA_string_set(&ptr, "parent", parname);
RNA_string_set(&ptr, "child", childname);
RNA_enum_set(&ptr, "type", PAR_LATTICE);
- uiItemFullO_ptr(layout, ot, IFACE_("Lattice Deform"), 0, ptr.data, WM_OP_EXEC_DEFAULT, 0);
}
UI_popup_menu_end(C, pup);
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 768fe4d8551..2256e55a315 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -37,6 +37,7 @@
/* internal exports only */
struct wmOperatorType;
+struct TreeElement;
struct TreeStoreElem;
struct bContext;
struct Scene;
@@ -45,6 +46,39 @@ struct ID;
struct Object;
struct bPoseChannel;
struct EditBone;
+struct wmKeyConfig;
+
+
+typedef enum TreeElementInsertType {
+ TE_INSERT_BEFORE,
+ TE_INSERT_AFTER,
+ TE_INSERT_INTO,
+} TreeElementInsertType;
+
+typedef enum TreeTraversalAction {
+ /* Continue traversal regularly, don't skip children. */
+ TRAVERSE_CONTINUE = 0,
+ /* Stop traversal */
+ TRAVERSE_BREAK,
+ /* Continue traversal, but skip childs of traversed element */
+ TRAVERSE_SKIP_CHILDS,
+} TreeTraversalAction;
+
+/**
+ * Callback type for reinserting elements at a different position, used to allow user customizable element order.
+ * Passing scene right now, may be better to allow some custom data.
+ */
+typedef void (*TreeElementReinsertFunc)(const struct Scene *scene, struct TreeElement *insert_element,
+ struct TreeElement *insert_handle, TreeElementInsertType action);
+/**
+ * Executed on (almost) each mouse move while dragging. It's supposed to give info
+ * if reinserting insert_element before/after/into insert_handle would be allowed.
+ * It's allowed to change the reinsert info here for non const pointers.
+ */
+typedef bool (*TreeElementReinsertPollFunc)(const struct Scene *scene, const struct TreeElement *insert_element,
+ struct TreeElement **io_insert_handle, TreeElementInsertType *io_action);
+typedef TreeTraversalAction (*TreeTraversalFunc)(struct TreeElement *te, void *customdata);
+
typedef struct TreeElement {
struct TreeElement *next, *prev, *parent;
@@ -58,7 +92,17 @@ typedef struct TreeElement {
const char *name;
void *directdata; // Armature Bones, Base, Sequence, Strip...
PointerRNA rnaptr; // RNA Pointer
-} TreeElement;
+
+ /* callbacks - TODO should be moved into a type (like TreeElementType) */
+ TreeElementReinsertFunc reinsert;
+ TreeElementReinsertPollFunc reinsert_poll;
+
+ struct {
+ TreeElementInsertType insert_type;
+ /* the element before/after/into which we may insert the dragged one (NULL to insert at top) */
+ struct TreeElement *insert_handle;
+ } *drag_data;
+} TreeElement;
#define TREESTORE_ID_TYPE(_id) \
(ELEM(GS((_id)->name), ID_SCE, ID_LI, ID_OB, ID_ME, ID_CU, ID_MB, ID_NT, ID_MA, ID_TE, ID_IM, ID_LT, ID_LA, ID_CA) || \
@@ -134,13 +178,7 @@ typedef enum {
void outliner_free_tree(ListBase *lb);
void outliner_cleanup_tree(struct SpaceOops *soops);
-
-TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
-TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
-TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
-TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
-TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
-struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
+void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem);
void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct SceneLayer *sl, struct SpaceOops *soops);
@@ -163,11 +201,11 @@ typedef void (*outliner_operation_cb)(
struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *, void *);
void outliner_do_object_operation_ex(
- struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
- outliner_operation_cb operation_cb, bool recurse_selected);
+ struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops,
+ struct ListBase *lb, outliner_operation_cb operation_cb, bool recurse_selected);
void outliner_do_object_operation(
- struct bContext *C, ReportList *reports, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
- outliner_operation_cb operation_cb);
+ struct bContext *C, struct ReportList *reports, struct Scene *scene, struct SpaceOops *soops,
+ struct ListBase *lb, outliner_operation_cb operation_cb);
int common_restrict_check(struct bContext *C, struct Object *ob);
@@ -214,9 +252,6 @@ void id_remap_cb(
TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const bool children);
-TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
-TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
-
/* ...................................................... */
void OUTLINER_OT_highlight_update(struct wmOperatorType *ot);
@@ -268,10 +303,40 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot);
void OUTLINER_OT_action_set(struct wmOperatorType *ot);
void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot);
void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_operation(struct wmOperatorType *ot);
/* ---------------------------------------------------------------- */
/* outliner_ops.c */
void outliner_operatortypes(void);
void outliner_keymap(struct wmKeyConfig *keyconf);
+/* outliner_collections.c */
+
+struct SceneCollection *outliner_scene_collection_from_tree_element(TreeElement *te);
+
+void OUTLINER_OT_collections_delete(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_select(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_override_new(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_add(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
+
+/* outliner_utils.c ---------------------------------------------- */
+
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y);
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x);
+TreeElement *outliner_find_tse(struct SpaceOops *soops, const TreeStoreElem *tse);
+TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
+TreeElement *outliner_find_id(struct SpaceOops *soops, ListBase *lb, const struct ID *id);
+TreeElement *outliner_find_posechannel(ListBase *lb, const struct bPoseChannel *pchan);
+TreeElement *outliner_find_editbone(ListBase *lb, const struct EditBone *ebone);
+struct ID *outliner_search_back(SpaceOops *soops, TreeElement *te, short idcode);
+bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
+ TreeTraversalFunc func, void *customdata);
+
+
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index 5ddfdddc80d..90d27b09292 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -28,17 +28,253 @@
* \ingroup spoutliner
*/
-#include "DNA_space_types.h"
+#include "BKE_context.h"
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
#include "RNA_access.h"
+#include "UI_interface.h"
+#include "UI_view2d.h"
+
#include "WM_api.h"
#include "WM_types.h"
#include "outliner_intern.h"
+enum {
+ OUTLINER_ITEM_DRAG_CANCEL,
+ OUTLINER_ITEM_DRAG_CONFIRM,
+};
+
+static int outliner_item_drag_drop_poll(bContext *C)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ return ED_operator_outliner_active(C) &&
+ /* Only collection display modes supported for now. Others need more design work */
+ ELEM(soops->outlinevis, SO_ACT_LAYER, SO_COLLECTIONS);
+}
+
+static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
+{
+ /* note: using EVT_TWEAK_ events to trigger dragging is fine,
+ * it sends coordinates from where dragging was started */
+ const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
+ return outliner_find_item_at_y(soops, &soops->tree, my);
+}
+
+static void outliner_item_drag_end(TreeElement *dragged_te)
+{
+ MEM_SAFE_FREE(dragged_te->drag_data);
+}
+
+static void outliner_item_drag_get_insert_data(
+ const SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged,
+ TreeElement **r_te_insert_handle, TreeElementInsertType *r_insert_type)
+{
+ TreeElement *te_hovered;
+ float view_mval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ te_hovered = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (te_hovered) {
+ /* mouse hovers an element (ignoring x-axis), now find out how to insert the dragged item exactly */
+
+ if (te_hovered == te_dragged) {
+ *r_te_insert_handle = te_dragged;
+ }
+ else if (te_hovered != te_dragged) {
+ const float margin = UI_UNIT_Y * (1.0f / 4);
+
+ *r_te_insert_handle = te_hovered;
+ if (view_mval[1] < (te_hovered->ys + margin)) {
+ if (TSELEM_OPEN(TREESTORE(te_hovered), soops)) {
+ /* inserting after a open item means we insert into it, but as first child */
+ if (BLI_listbase_is_empty(&te_hovered->subtree)) {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+ else {
+ *r_insert_type = TE_INSERT_BEFORE;
+ *r_te_insert_handle = te_hovered->subtree.first;
+ }
+ }
+ else {
+ *r_insert_type = TE_INSERT_AFTER;
+ }
+ }
+ else if (view_mval[1] > (te_hovered->ys + (3 * margin))) {
+ *r_insert_type = TE_INSERT_BEFORE;
+ }
+ else {
+ *r_insert_type = TE_INSERT_INTO;
+ }
+ }
+ }
+ else {
+ /* mouse doesn't hover any item (ignoring x-axis), so it's either above list bounds or below. */
+
+ TreeElement *first = soops->tree.first;
+ TreeElement *last = soops->tree.last;
+
+ if (view_mval[1] < last->ys) {
+ *r_te_insert_handle = last;
+ *r_insert_type = TE_INSERT_AFTER;
+ }
+ else if (view_mval[1] > (first->ys + UI_UNIT_Y)) {
+ *r_te_insert_handle = first;
+ *r_insert_type = TE_INSERT_BEFORE;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+}
+
+static void outliner_item_drag_handle(
+ const Scene *scene, SpaceOops *soops, ARegion *ar, const wmEvent *event, TreeElement *te_dragged)
+{
+ TreeElement *te_insert_handle;
+ TreeElementInsertType insert_type;
+
+ outliner_item_drag_get_insert_data(soops, ar, event, te_dragged, &te_insert_handle, &insert_type);
+
+ if (!te_dragged->reinsert_poll &&
+ /* there is no reinsert_poll, so we do some generic checks (same types and reinsert callback is available) */
+ (TREESTORE(te_dragged)->type == TREESTORE(te_insert_handle)->type) &&
+ te_dragged->reinsert)
+ {
+ /* pass */
+ }
+ else if (te_dragged == te_insert_handle) {
+ /* nothing will happen anyway, no need to do poll check */
+ }
+ else if (!te_dragged->reinsert_poll ||
+ !te_dragged->reinsert_poll(scene, te_dragged, &te_insert_handle, &insert_type))
+ {
+ te_insert_handle = NULL;
+ }
+ te_dragged->drag_data->insert_type = insert_type;
+ te_dragged->drag_data->insert_handle = te_insert_handle;
+}
+
+static bool outliner_item_drag_drop_apply(const Scene *scene, TreeElement *dragged_te)
+{
+ TreeElement *insert_handle = dragged_te->drag_data->insert_handle;
+ TreeElementInsertType insert_type = dragged_te->drag_data->insert_type;
+
+ if ((insert_handle == dragged_te) || !insert_handle) {
+ /* No need to do anything */
+ }
+ else if (dragged_te->reinsert) {
+ BLI_assert(!dragged_te->reinsert_poll || dragged_te->reinsert_poll(scene, dragged_te, &insert_handle,
+ &insert_type));
+ /* call of assert above should not have changed insert_handle and insert_type at this point */
+ BLI_assert(dragged_te->drag_data->insert_handle == insert_handle &&
+ dragged_te->drag_data->insert_type == insert_type);
+ dragged_te->reinsert(scene, dragged_te, insert_handle, insert_type);
+ return true;
+ }
+
+ return false;
+}
+
+static int outliner_item_drag_drop_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te_dragged = op->customdata;
+ int retval = OPERATOR_RUNNING_MODAL;
+ bool redraw = false;
+ bool skip_rebuild = true;
+
+ switch (event->type) {
+ case EVT_MODAL_MAP:
+ if (event->val == OUTLINER_ITEM_DRAG_CONFIRM) {
+ if (outliner_item_drag_drop_apply(scene, te_dragged)) {
+ skip_rebuild = false;
+ }
+ retval = OPERATOR_FINISHED;
+ }
+ else if (event->val == OUTLINER_ITEM_DRAG_CANCEL) {
+ retval = OPERATOR_CANCELLED;
+ }
+ else {
+ BLI_assert(0);
+ }
+ WM_event_add_mousemove(C); /* update highlight */
+ outliner_item_drag_end(te_dragged);
+ redraw = true;
+ break;
+ case MOUSEMOVE:
+ outliner_item_drag_handle(scene, soops, ar, event, te_dragged);
+ redraw = true;
+ break;
+ }
+
+ if (skip_rebuild) {
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ }
+ if (redraw) {
+ ED_region_tag_redraw(ar);
+ }
+
+ return retval;
+}
+
+static int outliner_item_drag_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ TreeElement *te_dragged = outliner_item_drag_element_find(soops, ar, event);
+
+ if (!te_dragged) {
+ return (OPERATOR_FINISHED | OPERATOR_PASS_THROUGH);
+ }
+
+ op->customdata = te_dragged;
+ te_dragged->drag_data = MEM_callocN(sizeof(*te_dragged->drag_data), __func__);
+ /* by default we don't change the item position */
+ te_dragged->drag_data->insert_handle = te_dragged;
+ /* unset highlighted tree element, dragged one will be highlighted instead */
+ outliner_set_flag(&soops->tree, TSE_HIGHLIGHTED, false);
+
+ soops->storeflag |= SO_TREESTORE_REDRAW; /* only needs to redraw, no rebuild */
+ ED_region_tag_redraw(ar);
+
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+/**
+ * Notes about Outliner Item Drag 'n Drop:
+ * Right now only collections display mode is supported. But ideally all/most modes would support this. There are
+ * just some open design questions that have to be answered: do we want to allow mixing order of different data types
+ * (like render-layers and objects)? Would that be a purely visual change or would that have any other effect? ...
+ */
+static void OUTLINER_OT_item_drag_drop(wmOperatorType *ot)
+{
+ ot->name = "Drag and Drop Item";
+ ot->idname = "OUTLINER_OT_item_drag_drop";
+ ot->description = "Change the hierarchical position of an item by repositioning it using drag and drop";
+
+ ot->invoke = outliner_item_drag_drop_invoke;
+ ot->modal = outliner_item_drag_drop_modal;
+
+ ot->poll = outliner_item_drag_drop_poll;
+
+ ot->flag = OPTYPE_UNDO;
+}
+
+
/* ************************** registration **********************************/
void outliner_operatortypes(void)
@@ -48,6 +284,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_select_border);
WM_operatortype_append(OUTLINER_OT_item_openclose);
WM_operatortype_append(OUTLINER_OT_item_rename);
+ WM_operatortype_append(OUTLINER_OT_item_drag_drop);
WM_operatortype_append(OUTLINER_OT_operation);
WM_operatortype_append(OUTLINER_OT_scene_operation);
WM_operatortype_append(OUTLINER_OT_object_operation);
@@ -62,6 +299,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_action_set);
WM_operatortype_append(OUTLINER_OT_constraint_operation);
WM_operatortype_append(OUTLINER_OT_modifier_operation);
+ WM_operatortype_append(OUTLINER_OT_collection_operation);
WM_operatortype_append(OUTLINER_OT_show_one_level);
WM_operatortype_append(OUTLINER_OT_show_active);
@@ -84,6 +322,48 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_scene_drop);
WM_operatortype_append(OUTLINER_OT_material_drop);
WM_operatortype_append(OUTLINER_OT_group_link);
+
+ /* collections */
+ WM_operatortype_append(OUTLINER_OT_collections_delete);
+ WM_operatortype_append(OUTLINER_OT_collection_select);
+ WM_operatortype_append(OUTLINER_OT_collection_link);
+ WM_operatortype_append(OUTLINER_OT_collection_unlink);
+ WM_operatortype_append(OUTLINER_OT_collection_new);
+ WM_operatortype_append(OUTLINER_OT_collection_override_new);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_add);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_remove);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_select);
+ WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
+}
+
+static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
+{
+ static EnumPropertyItem modal_items[] = {
+ {OUTLINER_ITEM_DRAG_CANCEL, "CANCEL", 0, "Cancel", ""},
+ {OUTLINER_ITEM_DRAG_CONFIRM, "CONFIRM", 0, "Confirm/Drop", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+ const char *map_name = "Outliner Item Drap 'n Drop Modal Map";
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, map_name);
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items)
+ return NULL;
+
+ keymap = WM_modalkeymap_add(keyconf, map_name, modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL);
+ WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, OUTLINER_ITEM_DRAG_CANCEL);
+
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+ WM_modalkeymap_add_item(keymap, RETKEY, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+ WM_modalkeymap_add_item(keymap, PADENTER, KM_RELEASE, KM_ANY, 0, OUTLINER_ITEM_DRAG_CONFIRM);
+
+ WM_modalkeymap_assign(keymap, "OUTLINER_OT_item_drag_drop");
+
+ return keymap;
}
void outliner_keymap(wmKeyConfig *keyconf)
@@ -122,6 +402,8 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_operation", RIGHTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "OUTLINER_OT_item_drag_drop", EVT_TWEAK_L, KM_ANY, 0, 0);
+
WM_keymap_add_item(keymap, "OUTLINER_OT_show_hierarchy", HOMEKEY, KM_PRESS, 0, 0);
WM_keymap_add_item(keymap, "OUTLINER_OT_show_active", PERIODKEY, KM_PRESS, 0, 0);
@@ -148,5 +430,7 @@ void outliner_keymap(wmKeyConfig *keyconf)
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_add_selected", DKEY, KM_PRESS, 0, 0);
WM_keymap_verify_item(keymap, "OUTLINER_OT_drivers_delete_selected", DKEY, KM_PRESS, KM_ALT, 0);
+
+ outliner_item_drag_drop_modal_keymap(keyconf);
}
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 1fad5f26218..0707f728ff7 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -186,7 +186,7 @@ static eOLDrawState tree_element_set_active_object(
do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0);
}
- if (C) {
+ if (set != OL_SETSEL_NONE) {
ED_object_base_activate(C, base); /* adds notifier */
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -199,7 +199,7 @@ static eOLDrawState tree_element_set_active_object(
}
static eOLDrawState tree_element_active_material(
- bContext *C, Scene* UNUSED(scene), SceneLayer *sl, SpaceOops *soops,
+ bContext *C, Scene *UNUSED(scene), SceneLayer *sl, SpaceOops *soops,
TreeElement *te, const eOLSetState set)
{
TreeElement *tes;
@@ -755,18 +755,32 @@ static eOLDrawState tree_element_active_keymap_item(
}
static eOLDrawState tree_element_active_collection(
- bContext *C, TreeElement *te, TreeStoreElem *UNUSED(tselem), const eOLSetState set)
+ bContext *C, TreeElement *te, TreeStoreElem *tselem, const eOLSetState set)
{
- if (set != OL_SETSEL_NONE) {
- Scene *scene = CTX_data_scene(C);
- SceneLayer *slayer = BLI_findlink(&scene->render_layers, scene->active_layer);
- LayerCollection *collection = te->directdata;
- const int collection_index = BKE_layer_collection_findindex(slayer, collection);
+ if (set == OL_SETSEL_NONE) {
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ /* sometimes the renderlayer has no LayerCollection at all */
+ if (active == NULL) {
+ return OL_DRAWSEL_NONE;
+ }
+
+ if ((tselem->type == TSE_SCENE_COLLECTION && active->scene_collection == te->directdata) ||
+ (tselem->type == TSE_LAYER_COLLECTION && active == te->directdata))
+ {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ /* don't allow selecting a scene collection, it can have multiple layer collection
+ * instances (which one would the user want to be selected then?) */
+ else if (tselem->type == TSE_LAYER_COLLECTION) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ LayerCollection *lc = te->directdata;
+ const int collection_index = BKE_layer_collection_findindex(sl, lc);
BLI_assert(collection_index >= 0);
- slayer->active_collection = collection_index;
+ sl->active_collection = collection_index;
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
- return OL_DRAWSEL_ACTIVE;
}
return OL_DRAWSEL_NONE;
@@ -787,25 +801,23 @@ eOLDrawState tree_element_active(bContext *C, Scene *scene, SceneLayer *sl, Spac
}
break;
case ID_MA:
- return tree_element_active_material(C, scene, sl, soops, te, set);
+ return tree_element_active_material(C, scene, sl, soops, te, set);
case ID_WO:
- return tree_element_active_world(C, scene, sl, soops, te, set);
+ return tree_element_active_world(C, scene, sl, soops, te, set);
case ID_LA:
- return tree_element_active_lamp(C, scene, sl, soops, te, set);
+ return tree_element_active_lamp(C, scene, sl, soops, te, set);
case ID_TE:
- return tree_element_active_texture(C, scene, sl, soops, te, set);
+ return tree_element_active_texture(C, scene, sl, soops, te, set);
case ID_TXT:
- return tree_element_active_text(C, scene, sl, soops, te, set);
+ return tree_element_active_text(C, scene, sl, soops, te, set);
case ID_CA:
- return tree_element_active_camera(C, scene, sl, soops, te, set);
+ return tree_element_active_camera(C, scene, sl, soops, te, set);
}
return OL_DRAWSEL_NONE;
}
/**
* Generic call for non-id data to make/check active in UI
- *
- * \note Context can be NULL when ``(set == OL_SETSEL_NONE)``
*/
eOLDrawState tree_element_type_active(
bContext *C, Scene *scene, SceneLayer *sl, SpaceOops *soops,
@@ -819,7 +831,7 @@ eOLDrawState tree_element_type_active(
case TSE_EBONE:
return tree_element_active_ebone(C, scene, te, tselem, set, recursive);
case TSE_MODIFIER:
- return tree_element_active_modifier(C, scene, sl, te, tselem, set);
+ return tree_element_active_modifier(C, scene, sl, te, tselem, set);
case TSE_LINKED_OB:
if (set != OL_SETSEL_NONE) {
tree_element_set_active_object(C, scene, sl, soops, te, set, false);
@@ -833,23 +845,24 @@ eOLDrawState tree_element_type_active(
case TSE_POSE_BASE:
return tree_element_active_pose(C, scene, sl, te, tselem, set);
case TSE_POSE_CHANNEL:
- return tree_element_active_posechannel(C, scene, sl, te, tselem, set, recursive);
+ return tree_element_active_posechannel(C, scene, sl, te, tselem, set, recursive);
case TSE_CONSTRAINT:
- return tree_element_active_constraint(C, scene, sl, te, tselem, set);
+ return tree_element_active_constraint(C, scene, sl, te, tselem, set);
case TSE_R_LAYER:
- return tree_element_active_renderlayer(C, scene, sl, te, tselem, set);
+ return tree_element_active_renderlayer(C, scene, sl, te, tselem, set);
case TSE_POSEGRP:
- return tree_element_active_posegroup(C, scene, sl, te, tselem, set);
+ return tree_element_active_posegroup(C, scene, sl, te, tselem, set);
case TSE_SEQUENCE:
return tree_element_active_sequence(C, scene, te, tselem, set);
case TSE_SEQUENCE_DUP:
return tree_element_active_sequence_dup(scene, te, tselem, set);
case TSE_KEYMAP_ITEM:
- return tree_element_active_keymap_item(C, scene, sl, te, tselem, set);
+ return tree_element_active_keymap_item(C, scene, sl, te, tselem, set);
case TSE_GP_LAYER:
- //return tree_element_active_gplayer(C, scene, s, te, tselem, set);
+ //return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
- case TSE_COLLECTION:
+ case TSE_SCENE_COLLECTION:
+ case TSE_LAYER_COLLECTION:
return tree_element_active_collection(C, te, tselem, set);
}
return OL_DRAWSEL_NONE;
@@ -868,7 +881,7 @@ static void outliner_item_activate(
/* always makes active object, except for some specific types.
* Note about TSE_EBONE: In case of a same ID_AR datablock shared among several objects, we do not want
* to switch out of edit mode (see T48328 for details). */
- if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_COLLECTION)) {
+ if (!ELEM(tselem->type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP, TSE_EBONE, TSE_LAYER_COLLECTION)) {
tree_element_set_active_object(C, scene, sl, soops, te,
(extend && tselem->type == 0) ? OL_SETSEL_EXTEND : OL_SETSEL_NORMAL,
recursive && tselem->type == 0);
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 550dc63dd3c..34879c09583 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -648,6 +648,14 @@ typedef enum eOutliner_PropModifierOps {
OL_MODIFIER_OP_DELETE
} eOutliner_PropModifierOps;
+typedef enum eOutliner_PropCollectionOps {
+ OL_COLLECTION_OP_OBJECTS_ADD = 1,
+ OL_COLLECTION_OP_OBJECTS_REMOVE,
+ OL_COLLECTION_OP_COLLECTION_NEW,
+ OL_COLLECTION_OP_COLLECTION_DEL,
+ OL_COLLECTION_OP_COLLECTION_UNLINK,
+} eOutliner_PropCollectionOps;
+
static void pchan_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *UNUSED(arg))
{
bPoseChannel *pchan = (bPoseChannel *)te->directdata;
@@ -798,6 +806,63 @@ static void modifier_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem
}
}
+static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tselem), void *Carg)
+{
+ bContext *C = (bContext *)Carg;
+ Scene *scene = CTX_data_scene(C);
+ LayerCollection *lc = te->directdata;
+ SceneCollection *sc = lc->scene_collection;
+
+ if (event == OL_COLLECTION_OP_OBJECTS_ADD) {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ BKE_collection_object_add(scene, sc, ob);
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (event == OL_COLLECTION_OP_OBJECTS_REMOVE) {
+ Main *bmain = CTX_data_main(C);
+
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+ {
+ BKE_collection_object_remove(bmain, scene, sc, ob, true);
+ }
+ CTX_DATA_END;
+
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ te->store_elem->flag &= ~TSE_SELECTED;
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_NEW) {
+ BKE_collection_add(scene, sc, NULL);
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+
+ if (BLI_findindex(&sl->layer_collections, lc) == -1) {
+ /* we can't unlink if the layer collection wasn't directly linked */
+ TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
+ }
+ else {
+ BKE_collection_unlink(sl, lc);
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ }
+ else if (event == OL_COLLECTION_OP_COLLECTION_DEL) {
+ if (BKE_collection_remove(scene, sc)) {
+ DAG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+ }
+ else {
+ /* we can't remove the master collection */
+ TODO_LAYER_OPERATORS; /* this shouldn't be in the menu in those cases */
+ }
+ }
+}
+
static void outliner_do_data_operation(SpaceOops *soops, int type, int event, ListBase *lb,
void (*operation_cb)(int, TreeElement *, TreeStoreElem *, void *),
void *arg)
@@ -1238,6 +1303,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
if (idlevel > 0) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete");
}
break;
}
@@ -1245,6 +1311,7 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
{
if (idlevel > 0) {
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_remap_cb, NULL);
+ ED_undo_push(C, "Remap");
}
break;
}
@@ -1353,18 +1420,20 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op)
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, item_rename_cb, NULL);
WM_event_add_notifier(C, NC_ID | NA_EDITED, NULL);
- ED_undo_push(C, "Rename");
+ ED_undo_push(C, "Rename Library");
break;
}
case OL_LIB_DELETE:
{
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, id_delete_cb, NULL);
+ ED_undo_push(C, "Delete Library");
break;
}
case OL_LIB_RELOCATE:
{
/* rename */
outliner_do_libdata_operation(C, op->reports, scene, soops, &soops->tree, lib_relocate_cb, NULL);
+ ED_undo_push(C, "Relocate Library");
break;
}
case OL_LIB_RELOAD:
@@ -1723,6 +1792,52 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot)
/* ******************** */
+static EnumPropertyItem prop_collection_op_types[] = {
+ {OL_COLLECTION_OP_OBJECTS_ADD, "OBJECTS_ADD", ICON_ZOOMIN, "Add Selected", "Add selected objects to collection"},
+ {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"},
+ {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"},
+ {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"},
+ {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_NEW", ICON_X, "Delete Collection", "Delete the collection"},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static int outliner_collection_operation_exec(bContext *C, wmOperator *op)
+{
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0;
+ eOutliner_PropCollectionOps event;
+
+ event = RNA_enum_get(op->ptr, "type");
+ set_operation_types(soops, &soops->tree, &scenelevel, &objectlevel, &idlevel, &datalevel);
+
+ outliner_do_data_operation(soops, datalevel, event, &soops->tree, collection_cb, C);
+
+ outliner_cleanup_tree(soops);
+
+ ED_undo_push(C, "Collection operation");
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_operation(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Outliner Collection Operation";
+ ot->idname = "OUTLINER_OT_collection_operation";
+ ot->description = "";
+
+ /* callbacks */
+ ot->invoke = WM_menu_invoke;
+ ot->exec = outliner_collection_operation_exec;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag = 0;
+
+ ot->prop = RNA_def_enum(ot->srna, "type", prop_collection_op_types, 0, "Collection Operation", "");
+}
+
+/* ******************** */
+
// XXX: select linked is for RNA structs only
static EnumPropertyItem prop_data_op_types[] = {
{OL_DOP_SELECT, "SELECT", 0, "Select", ""},
@@ -1897,6 +2012,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_MODIFIER) {
WM_operator_name_call(C, "OUTLINER_OT_modifier_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
+ else if (datalevel == TSE_LAYER_COLLECTION) {
+ WM_operator_name_call(C, "OUTLINER_OT_collection_operation", WM_OP_INVOKE_REGION_WIN, NULL);
+ }
else {
WM_operator_name_call(C, "OUTLINER_OT_data_operation", WM_OP_INVOKE_REGION_WIN, NULL);
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index c96d7f970ed..a14df17c088 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -84,6 +84,9 @@
# include "BLI_math_base.h" /* M_PI */
#endif
+/* prototypes */
+static void outliner_make_hierarchy(ListBase *lb);
+
/* ********************************************************* */
/* Persistent Data */
@@ -200,105 +203,6 @@ void outliner_cleanup_tree(SpaceOops *soops)
outliner_storage_cleanup(soops);
}
-/* Find specific item from the treestore */
-TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
-{
- TreeElement *te, *tes;
- for (te = lb->first; te; te = te->next) {
- if (te->store_elem == store_elem) return te;
- tes = outliner_find_tree_element(&te->subtree, store_elem);
- if (tes) return tes;
- }
- return NULL;
-}
-
-/* tse is not in the treestore, we use its contents to find a match */
-TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
-{
- TreeStoreElem *tselem;
-
- if (tse->id == NULL) return NULL;
-
- /* check if 'tse' is in treestore */
- tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
- if (tselem)
- return outliner_find_tree_element(&soops->tree, tselem);
-
- return NULL;
-}
-
-/* Find treestore that refers to given ID */
-TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0) {
- if (tselem->id == id) {
- return te;
- }
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
- TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
- if (tes) {
- return tes;
- }
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == pchan) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
- TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == ebone) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, 0, TSE_EBONE)) {
- TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
-{
- TreeStoreElem *tselem;
- te = te->parent;
-
- while (te) {
- tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == idcode) return tselem->id;
- te = te->parent;
- }
- return NULL;
-}
-
/* ********************************************************* */
@@ -484,12 +388,55 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
#endif
}
+static void outliner_object_reorder(
+ const Scene *scene, TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ TreeStoreElem *tselem_insert = TREESTORE(insert_element);
+ Object *ob = (Object *)tselem_insert->id;
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
+ SceneCollection *sc_ob_parent = NULL;
+
+ BLI_assert(action == TE_INSERT_INTO);
+ UNUSED_VARS_NDEBUG(action);
+
+ /* find parent scene-collection of object */
+ if (insert_element->parent) {
+ for (TreeElement *te_ob_parent = insert_element->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
+ if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
+ sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ break;
+ }
+ }
+ }
+ else {
+ sc_ob_parent = BKE_collection_master(scene);
+ }
+ BKE_collection_object_move(scene, sc, sc_ob_parent, ob);
+}
+static bool outliner_object_reorder_poll(
+ const Scene *UNUSED(scene), const TreeElement *insert_element,
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ (insert_element->parent != *io_insert_handle))
+ {
+ *io_action = TE_INSERT_INTO;
+ return true;
+ }
+
+ return false;
+}
+
// can be inlined if necessary
static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, Object *ob)
{
+ te->reinsert = outliner_object_reorder;
+ te->reinsert_poll = outliner_object_reorder_poll;
+
if (outliner_animdata_test(ob->adt))
outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
-
+
outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
if (ob->proxy && !ID_IS_LINKED_DATABLOCK(ob))
@@ -905,7 +852,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
}
/* exceptions */
- if (ELEM(type, TSE_ID_BASE, TSE_COLLECTION)) {
+ if (ELEM(type, TSE_ID_BASE, TSE_LAYER_COLLECTION)) {
/* pass */
}
else if (id == NULL) {
@@ -942,7 +889,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (type == TSE_COLLECTION) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -1237,6 +1184,15 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
return te;
}
+/**
+ * \note Really only removes \a tselem, not it's TreeElement instance or any children.
+ */
+void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem)
+{
+ BKE_outliner_treehash_remove_element(soops->treehash, tselem);
+ BLI_mempool_free(soops->treestore, tselem);
+}
+
/* ======================================================= */
/* Sequencer mode tree building */
@@ -1374,22 +1330,126 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
-static void outliner_add_collections_recursive(SpaceOops *soops, ListBase *tree, ListBase *layer_collections,
- TreeElement *parent_ten)
+static void outliner_layer_collections_reorder(
+ const Scene *scene, TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ LayerCollection *lc_insert = insert_element->directdata;
+ LayerCollection *lc_handle = insert_handle->directdata;
+
+ if (action == TE_INSERT_BEFORE) {
+ BKE_layer_collection_move_above(scene, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_layer_collection_move_below(scene, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_layer_collection_move_into(scene, lc_handle, lc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+static bool outliner_layer_collections_reorder_poll(
+ const Scene *UNUSED(scene), const TreeElement *UNUSED(insert_element),
+ TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+}
+
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ListBase *layer_collections, TreeElement *parent_ten)
{
for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
- TreeElement *ten = outliner_add_element(soops, tree, NULL, parent_ten, TSE_COLLECTION, 0);
+ TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_LAYER_COLLECTION, 0);
ten->name = collection->scene_collection->name;
ten->directdata = collection;
+ ten->reinsert = outliner_layer_collections_reorder;
+ ten->reinsert_poll = outliner_layer_collections_reorder_poll;
+
+ for (LinkData *link = collection->object_bases.first; link; link = link->next) {
+ outliner_add_element(soops, &ten->subtree, ((Base *)link->data)->object, ten, 0, 0);
+ }
+ outliner_make_hierarchy(&ten->subtree);
+
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten);
+ }
+}
+static void outliner_add_collections_act_layer(SpaceOops *soops, SceneLayer *layer)
+{
+ outliner_add_layer_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL);
+}
+
+static void outliner_scene_collections_reorder(
+ const Scene *scene, TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ SceneCollection *sc_insert = insert_element->directdata;
+ SceneCollection *sc_handle = insert_handle->directdata;
+
+ BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(scene)));
+ if (action == TE_INSERT_BEFORE) {
+ BKE_collection_move_above(scene, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_collection_move_below(scene, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_collection_move_into(scene, sc_handle, sc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+}
+static bool outliner_scene_collections_reorder_poll(
+ const Scene *scene, const TreeElement *UNUSED(insert_element),
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc_handle = (*io_insert_handle)->directdata;
- outliner_add_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten);
+ if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
+ return false;
}
+
+ if (sc_handle == sc_master) {
+ /* exception: Can't insert before/after master selection, has to be one of its childs */
+ TreeElement *te_master = *io_insert_handle;
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = te_master->subtree.last;
+ }
+ }
+ return true;
}
-static void outliner_add_collections(SpaceOops *soops, SceneLayer *layer)
+static void outliner_add_scene_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ListBase *scene_collections, TreeElement *parent_ten)
+{
+ for (SceneCollection *collection = scene_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_SCENE_COLLECTION, 0);
+
+ ten->name = collection->name;
+ ten->directdata = collection;
+ ten->reinsert = outliner_scene_collections_reorder;
+ ten->reinsert_poll = outliner_scene_collections_reorder_poll;
+
+ for (LinkData *link = collection->objects.first; link; link = link->next) {
+ outliner_add_element(soops, &ten->subtree, link->data, ten, 0, 0);
+ }
+ outliner_make_hierarchy(&ten->subtree);
+
+ outliner_add_scene_collections_recursive(soops, &ten->subtree, &collection->scene_collections, ten);
+ }
+}
+static void outliner_add_collections_master(SpaceOops *soops, Scene *scene)
{
- outliner_add_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL);
+ SceneCollection *master = BKE_collection_master(scene);
+ outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL);
}
/* ======================================================= */
@@ -1505,18 +1565,15 @@ static void outliner_sort(ListBase *lb)
{
TreeElement *te;
TreeStoreElem *tselem;
- int totelem = 0;
te = lb->last;
if (te == NULL) return;
tselem = TREESTORE(te);
-
+
/* sorting rules; only object lists, ID lists, or deformgroups */
- if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
-
- /* count first */
- for (te = lb->first; te; te = te->next) totelem++;
-
+ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
+ int totelem = BLI_listbase_count(lb);
+
if (totelem > 1) {
tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array");
tTreeSort *tp = tear;
@@ -1724,7 +1781,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
if (sce == scene && show_opened)
tselem->flag &= ~TSE_CLOSED;
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
ten = outliner_add_element(soops, &te->subtree, ob, te, 0, 0);
@@ -1745,7 +1801,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
@@ -1754,7 +1809,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_VISIBLE) {
- Object *ob;
FOREACH_VISIBLE_OBJECT(sl, ob)
{
outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
@@ -1782,7 +1836,6 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
else if (soops->outlinevis == SO_SAME_TYPE) {
Object *ob_active = OBACT_NEW;
if (ob_active) {
- Object *ob;
FOREACH_SCENE_OBJECT(scene, ob)
{
if (ob->type == ob_active->type) {
@@ -1794,10 +1847,9 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
}
}
else if (soops->outlinevis == SO_SELECTED) {
- Object *ob;
FOREACH_SELECTED_OBJECT(sl, ob)
{
- ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
+ ten = outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
FOREACH_SELECTED_OBJECT_END
outliner_make_hierarchy(&soops->tree);
@@ -1853,8 +1905,11 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
+ else if (soops->outlinevis == SO_ACT_LAYER) {
+ outliner_add_collections_act_layer(soops, BKE_scene_layer_context_active(scene));
+ }
else if (soops->outlinevis == SO_COLLECTIONS) {
- outliner_add_collections(soops, BLI_findlink(&scene->render_layers, scene->active_layer));
+ outliner_add_collections_master(soops, scene);
}
else {
ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0);
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
new file mode 100644
index 00000000000..f123b240efc
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -0,0 +1,234 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_outliner/outliner_utils.c
+ * \ingroup spoutliner
+ */
+
+#include "BKE_outliner_treehash.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_action_types.h"
+#include "DNA_space_types.h"
+
+#include "ED_armature.h"
+
+#include "UI_interface.h"
+
+#include "outliner_intern.h"
+
+
+/**
+ * Try to find an item under y-coordinate \a view_co_y (view-space).
+ * \note Recursive
+ */
+TreeElement *outliner_find_item_at_y(const SpaceOops *soops, const ListBase *tree, float view_co_y)
+{
+ for (TreeElement *te_iter = tree->first; te_iter; te_iter = te_iter->next) {
+ if (view_co_y < (te_iter->ys + UI_UNIT_Y)) {
+ if (view_co_y >= te_iter->ys) {
+ /* co_y is inside this element */
+ return te_iter;
+ }
+ else if (TSELEM_OPEN(te_iter->store_elem, soops)) {
+ /* co_y is lower than current element, possibly inside children */
+ TreeElement *te_sub = outliner_find_item_at_y(soops, &te_iter->subtree, view_co_y);
+ if (te_sub) {
+ return te_sub;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Collapsed items can show their children as click-able icons. This function tries to find
+ * such an icon that represents the child item at x-coordinate \a view_co_x (view-space).
+ *
+ * \return a hovered child item or \a parent_te (if no hovered child found).
+ */
+TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeElement *parent_te, float view_co_x)
+{
+ if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) { /* if parent_te is opened, it doesn't show childs in row */
+ /* no recursion, items can only display their direct children in the row */
+ for (TreeElement *child_te = parent_te->subtree.first;
+ child_te && view_co_x >= child_te->xs; /* don't look further if co_x is smaller than child position*/
+ child_te = child_te->next)
+ {
+ if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) && (view_co_x < child_te->xend)) {
+ return child_te;
+ }
+ }
+ }
+
+ /* return parent if no child is hovered */
+ return (TreeElement *)parent_te;
+}
+
+/* Find specific item from the treestore */
+TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
+{
+ TreeElement *te, *tes;
+ for (te = lb->first; te; te = te->next) {
+ if (te->store_elem == store_elem) return te;
+ tes = outliner_find_tree_element(&te->subtree, store_elem);
+ if (tes) return tes;
+ }
+ return NULL;
+}
+
+/* tse is not in the treestore, we use its contents to find a match */
+TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
+{
+ TreeStoreElem *tselem;
+
+ if (tse->id == NULL) return NULL;
+
+ /* check if 'tse' is in treestore */
+ tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
+ if (tselem)
+ return outliner_find_tree_element(&soops->tree, tselem);
+
+ return NULL;
+}
+
+/* Find treestore that refers to given ID */
+TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (tselem->type == 0) {
+ if (tselem->id == id) {
+ return te;
+ }
+ /* only deeper on scene or object */
+ if (ELEM(te->idcode, ID_OB, ID_SCE) ||
+ ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
+ {
+ TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == pchan) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
+ TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
+}
+
+TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if (te->directdata == ebone) {
+ return te;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (ELEM(tselem->type, 0, TSE_EBONE)) {
+ TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
+ if (tes) {
+ return tes;
+ }
+ }
+ }
+ return NULL;
+}
+
+ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
+{
+ TreeStoreElem *tselem;
+ te = te->parent;
+
+ while (te) {
+ tselem = TREESTORE(te);
+ if (tselem->type == 0 && te->idcode == idcode) return tselem->id;
+ te = te->parent;
+ }
+ return NULL;
+}
+
+/**
+ * Iterate over all tree elements (pre-order traversal), executing \a func callback for
+ * each tree element matching the optional filters.
+ *
+ * \param filter_te_flag: If not 0, only TreeElements with this flag will be visited.
+ * \param filter_tselem_flag: Same as \a filter_te_flag, but for the TreeStoreElem.
+ * \param func: Custom callback to execute for each visited item.
+ */
+bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag,
+ TreeTraversalFunc func, void *customdata)
+{
+ for (TreeElement *te = tree->first, *te_next; te; te = te_next) {
+ TreeTraversalAction func_retval = TRAVERSE_CONTINUE;
+ /* in case te is freed in callback */
+ TreeStoreElem *tselem = TREESTORE(te);
+ ListBase subtree = te->subtree;
+ te_next = te->next;
+
+ if (filter_te_flag && (te->flag & filter_te_flag) == 0) {
+ /* skip */
+ }
+ else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) {
+ /* skip */
+ }
+ else {
+ func_retval = func(te, customdata);
+ }
+ /* Don't access te or tselem from now on! Might've been freed... */
+
+ if (func_retval == TRAVERSE_BREAK) {
+ return false;
+ }
+
+ if (func_retval == TRAVERSE_SKIP_CHILDS) {
+ /* skip */
+ }
+ else if (!outliner_tree_traverse(soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 759ef4e78e4..0014b1f048e 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -102,10 +102,14 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
if (GS(id->name) == ID_OB) {
/* Ensure item under cursor is valid drop target */
TreeElement *te = outliner_dropzone_find(soops, fmval, true);
+ TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
- if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) {
+ if (!te) {
+ /* pass */
+ }
+ else if (te->idcode == ID_OB && tselem->type == 0) {
Scene *scene;
- ID *te_id = TREESTORE(te)->id;
+ ID *te_id = tselem->id;
/* check if dropping self or parent */
if (te_id == id || (Object *)te_id == ((Object *)id)->parent)
@@ -122,6 +126,10 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e
return 1;
}
}
+ else if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ /* support adding object from different scene to collection */
+ return 1;
+ }
}
}
return 0;
@@ -308,6 +316,7 @@ static void outliner_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(s
case ND_RENDER_OPTIONS:
case ND_SEQUENCER:
case ND_LAYER:
+ case ND_LAYER_CONTENT:
case ND_WORLD:
ED_region_tag_redraw(ar);
break;
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index ede6b7ce469..46f212e3679 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -38,6 +38,8 @@
#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "DNA_scene_types.h"
#include "DNA_mask_types.h"
@@ -445,6 +447,7 @@ void SEQUENCER_OT_movieclip_strip_add(struct wmOperatorType *ot)
sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
prop = RNA_def_enum(ot->srna, "clip", DummyRNA_NULL_items, 0, "Clip", "");
RNA_def_enum_funcs(prop, RNA_movieclip_itemf);
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_MOVIECLIP);
RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
ot->prop = prop;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index b4cc1123176..1fea1a98e94 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -55,11 +55,10 @@
#include "IMB_colormanagement.h"
#include "IMB_imbuf.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
-#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_anim_api.h"
#include "ED_gpencil.h"
@@ -191,25 +190,35 @@ void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
}
}
-static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(View2D *v2d, const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq,
+ float x1, float y1, float x2, float y2, float stepsize, unsigned int pos)
{
/*
* x1 is the starting x value to draw the wave,
* x2 the end x value, same for y1 and y2
* stepsize is width of a pixel.
*/
+
+ /* offset x1 and x2 values, to match view min/max, if strip is out of bounds */
+ int x1_offset = max_ff(v2d->cur.xmin, x1);
+ int x2_offset = min_ff(v2d->cur.xmax + 1.0f, x2);
+
if (seq->sound && ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM))) {
- int i, j, pos;
- int length = floor((x2 - x1) / stepsize) + 1;
- float ymid = (y1 + y2) / 2;
- float yscale = (y2 - y1) / 2;
+ int i, j, p;
+ int length = floor((x2_offset - x1_offset) / stepsize) + 1;
+ float ymid = (y1 + y2) / 2.0f;
+ float yscale = (y2 - y1) / 2.0f;
float samplestep;
float startsample, endsample;
float value1, value2;
bSound *sound = seq->sound;
SoundWaveform *waveform;
-
+
+ if (length < 2) {
+ return;
+ }
+
if (!sound->spinlock) {
sound->spinlock = MEM_mallocN(sizeof(SpinLock), "sound_spinlock");
BLI_spin_init(sound->spinlock);
@@ -242,21 +251,27 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
samplestep = (endsample - startsample) * stepsize / (x2 - x1);
- if (length > floor((waveform->length - startsample) / samplestep))
- length = floor((waveform->length - startsample) / samplestep);
+ length = min_ii(floor((waveform->length - startsample) / samplestep), length);
+
+ if (length < 2) {
+ return;
+ }
+
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.5);
- glColor4f(1.0f, 1.0f, 1.0f, 0.5);
glEnable(GL_BLEND);
- glBegin(GL_TRIANGLE_STRIP);
+
+ immBegin(GL_TRIANGLE_STRIP, length * 2);
+
for (i = 0; i < length; i++) {
- float sampleoffset = startsample + i * samplestep;
- pos = sampleoffset;
+ float sampleoffset = startsample + ((x1_offset - x1) / stepsize + i) * samplestep;
+ p = sampleoffset;
- value1 = waveform->data[pos * 3];
- value2 = waveform->data[pos * 3 + 1];
+ value1 = waveform->data[p * 3];
+ value2 = waveform->data[p * 3 + 1];
if (samplestep > 1.0f) {
- for (j = pos + 1; (j < waveform->length) && (j < pos + samplestep); j++) {
+ for (j = p + 1; (j < waveform->length) && (j < p + samplestep); j++) {
if (value1 > waveform->data[j * 3])
value1 = waveform->data[j * 3];
@@ -266,34 +281,20 @@ static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequenc
}
else {
/* use simple linear interpolation */
- float f = sampleoffset - pos;
- value1 = (1.0f - f) * value1 + f * waveform->data[pos * 3 + 3];
- value2 = (1.0f - f) * value2 + f * waveform->data[pos * 3 + 4];
+ float f = sampleoffset - p;
+ value1 = (1.0f - f) * value1 + f * waveform->data[p * 3 + 3];
+ value2 = (1.0f - f) * value2 + f * waveform->data[p * 3 + 4];
}
- glVertex2f(x1 + i * stepsize, ymid + value1 * yscale);
- glVertex2f(x1 + i * stepsize, ymid + value2 * yscale);
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value1 * yscale);
+ immVertex2f(pos, x1_offset + i * stepsize, ymid + value2 * yscale);
}
- glEnd();
- glDisable(GL_BLEND);
- }
-}
-static void drawmeta_stipple(int value)
-{
- if (value) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE);
-
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0x8888);
- }
- else {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisable(GL_LINE_STIPPLE);
+ immEnd();
+
+ glDisable(GL_BLEND);
}
}
-
static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1, float x2, float y2)
{
/* note: this used to use SEQ_BEGIN/SEQ_END, but it messes up the
@@ -326,9 +327,6 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (seqm->flag & SEQ_MUTE)
- drawmeta_stipple(1);
-
for (seq = seqbase->first; seq; seq = seq->next) {
chan_min = min_ii(chan_min, seq->machine);
chan_max = max_ii(chan_max, seq->machine);
@@ -339,6 +337,10 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
col[3] = 196; /* alpha, used for all meta children */
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
for (seq = seqbase->first; seq; seq = seq->next) {
const int startdisp = seq->startdisp + offset;
const int enddisp = seq->enddisp + offset;
@@ -349,12 +351,16 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
float x2_chan = enddisp;
float y1_chan, y2_chan;
- if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
- drawmeta_stipple(1);
-
color3ubv_from_seq(scene, seq, col);
- glColor4ubv(col);
+ if ((seqm->flag & SEQ_MUTE) || (seq->flag & SEQ_MUTE)) {
+ col[3] = 64;
+ }
+ else {
+ col[3] = 196;
+ }
+
+ immUniformColor4ubv(col);
/* clamp within parent sequence strip bounds */
if (x1_chan < x1) x1_chan = x1;
@@ -363,20 +369,12 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
y1_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSBOTTOM);
y2_chan = y1 + y_chan + (draw_height * SEQ_STRIP_OFSTOP);
- glRectf(x1_chan, y1_chan, x2_chan, y2_chan);
-
- UI_GetColorPtrShade3ubv(col, col, -30);
- glColor4ubv(col);
- fdrawbox(x1_chan, y1_chan, x2_chan, y2_chan);
-
- if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
- drawmeta_stipple(0);
+ immRectf(pos, x1_chan, y1_chan, x2_chan, y2_chan);
}
}
- if (seqm->flag & SEQ_MUTE)
- drawmeta_stipple(0);
-
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -392,7 +390,7 @@ static float draw_seq_handle_size_get_clamped(Sequence *seq, const float pixelx)
}
/* draw a handle, for each end of a sequence strip */
-static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction)
+static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_clamped, const short direction, unsigned int pos)
{
float v1[2], v2[2], v3[2], rx1 = 0, rx2 = 0; //for triangles and rect
float x1, x2, y1, y2;
@@ -434,21 +432,31 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- if (seq->flag & whichsel) glColor4ub(0, 0, 0, 80);
- else if (seq->flag & SELECT) glColor4ub(255, 255, 255, 30);
- else glColor4ub(0, 0, 0, 22);
-
- glRectf(rx1, y1, rx2, y2);
-
- if (seq->flag & whichsel) glColor4ub(255, 255, 255, 200);
- else glColor4ub(0, 0, 0, 50);
+ if (seq->flag & whichsel) {
+ immUniformColor4ub(0, 0, 0, 80);
+ }
+ else if (seq->flag & SELECT) {
+ immUniformColor4ub(255, 255, 255, 30);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 22);
+ }
- glEnable(GL_POLYGON_SMOOTH);
- glBegin(GL_TRIANGLES);
- glVertex2fv(v1); glVertex2fv(v2); glVertex2fv(v3);
- glEnd();
+ immRectf(pos, rx1, y1, rx2, y2);
- glDisable(GL_POLYGON_SMOOTH);
+ if (seq->flag & whichsel) {
+ immUniformColor4ub(255, 255, 255, 200);
+ }
+ else {
+ immUniformColor4ub(0, 0, 0, 50);
+ }
+
+ immBegin(GL_TRIANGLES, 3);
+ immVertex2fv(pos, v1);
+ immVertex2fv(pos, v2);
+ immVertex2fv(pos, v3);
+ immEnd();
+
glDisable(GL_BLEND);
}
@@ -546,7 +554,8 @@ static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1,
if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
str[0] = 0;
str_len = 0;
- } else if (seq->sound) {
+ }
+ else if (seq->sound) {
str_len = BLI_snprintf(str, sizeof(str), "%s: %s | %d",
name, seq->sound->name, seq->len);
}
@@ -586,67 +595,10 @@ static void draw_seq_text(View2D *v2d, SpaceSeq *sseq, Sequence *seq, float x1,
UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
}
-/* draws a shaded strip, made from gradient + flat color + gradient */
-void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
+static void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq, unsigned int pos)
{
- float ymid1, ymid2;
-
- if (seq->flag & SEQ_MUTE) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_HALFTONE);
- }
-
- ymid1 = (y2 - y1) * 0.25f + y1;
- ymid2 = (y2 - y1) * 0.65f + y1;
-
- glBegin(GL_QUADS);
-
- if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; }
- else if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -50);
- /* else UI_GetColorPtrShade3ubv(col, col, 0); */ /* DO NOTHING */
-
- glColor3ubv(col);
-
- glVertex2f(x1, y1);
- glVertex2f(x2, y1);
-
- if (seq->flag & SEQ_INVALID_EFFECT) { col[0] = 255; col[1] = 0; col[2] = 255; }
- else if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5);
- else UI_GetColorPtrShade3ubv(col, col, -5);
-
- glColor3ubv((GLubyte *)col);
-
- glVertex2f(x2, ymid1);
- glVertex2f(x1, ymid1);
-
- glEnd();
-
- glRectf(x1, ymid1, x2, ymid2);
-
- glBegin(GL_QUADS);
-
- glVertex2f(x1, ymid2);
- glVertex2f(x2, ymid2);
-
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, -15);
- else UI_GetColorPtrShade3ubv(col, col, 25);
-
- glColor3ubv((GLubyte *)col);
-
- glVertex2f(x2, y2);
- glVertex2f(x1, y2);
-
- glEnd();
-
- if (seq->flag & SEQ_MUTE) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-}
-
-void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
-{
- float x1, x2, y1, y2, pixely, a;
- unsigned char col[3], blendcol[3];
+ float x1, x2, y1, y2, pixely;
+ unsigned char col[4], blendcol[3];
View2D *v2d = &ar->v2d;
x1 = seq->startdisp;
@@ -660,90 +612,82 @@ void draw_sequence_extensions(Scene *scene, ARegion *ar, Sequence *seq)
if (pixely <= 0) return; /* can happen when the view is split/resized */
blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
- if (seq->startofs) {
+
+ if (seq->startofs || seq->endofs) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
color3ubv_from_seq(scene, seq, col);
-
+
if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
+ UI_GetColorPtrShade3ubv(col, col, -50);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 64;
}
else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
+ if (seq->flag & SELECT) {
+ col[3] = 170;
+ }
+ else {
+ col[3] = 80;
+ }
}
-
- glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); //outline
-
- glDisable(GL_BLEND);
+ }
+
+ if (seq->startofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+ immUniformColor4ub(col[0], col[1], col[2], col[3] + 50);
+
+ imm_draw_line_box(pos, (float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1); /* outline */
}
if (seq->endofs) {
+ immUniformColor4ubv(col);
+ immRectf(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+
+ immUniformColor4ub(col[0], col[1], col[2], col[3] + 50);
+
+ imm_draw_line_box(pos, x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); /* outline */
+ }
+
+ if (seq->startofs || seq->endofs) {
+ glDisable(GL_BLEND);
+ }
+
+ if (seq->startstill || seq->endstill) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
+
color3ubv_from_seq(scene, seq, col);
-
- if (seq->flag & SELECT) {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
- glColor4ub(col[0], col[1], col[2], 170);
+ UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.5f, 60);
+
+ if (seq->flag & SEQ_MUTE) {
+ col[3] = 96;
}
else {
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
- glColor4ub(col[0], col[1], col[2], 110);
+ if (seq->flag & SELECT) {
+ col[3] = 255;
+ }
+ else {
+ col[3] = 170;
+ }
}
-
- glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
-
- if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
- else glColor4ub(col[0], col[1], col[2], 160);
-
- fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
-
- glDisable(GL_BLEND);
+
+ immUniformColor4ubv(col);
}
+
if (seq->startstill) {
- color3ubv_from_seq(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline(x1, a, (float)(seq->start), a);
- }
+ immRectf(pos, x1, y1, (float)(seq->start), y2);
}
if (seq->endstill) {
- color3ubv_from_seq(scene, seq, col);
- UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
- glColor3ubv((GLubyte *)col);
-
- draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
-
- /* feint pinstripes, helps see exactly which is extended and which isn't,
- * especially when the extension is very small */
- if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
- else UI_GetColorPtrShade3ubv(col, col, -16);
-
- glColor3ubv((GLubyte *)col);
-
- for (a = y1; a < y2; a += pixely * 2.0f) {
- fdrawline((float)(seq->start + seq->len), a, x2, a);
- }
+ immRectf(pos, (float)(seq->start + seq->len), y1, x2, y2);
+ }
+
+ if (seq->startstill || seq->endstill) {
+ glDisable(GL_BLEND);
}
}
@@ -757,8 +701,7 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
{
View2D *v2d = &ar->v2d;
float x1, x2, y1, y2;
- unsigned char col[3], background_col[3], is_single_image;
- float fcol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ unsigned char col[4], background_col[4], is_single_image;
const float handsize_clamped = draw_seq_handle_size_get_clamped(seq, pixelx);
/* we need to know if this is a single image/color or not for drawing */
@@ -770,72 +713,105 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
x2 = (seq->endstill) ? (seq->start + seq->len) : seq->enddisp;
y2 = seq->machine + SEQ_STRIP_OFSTOP;
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* get the correct color per strip type*/
//color3ubv_from_seq(scene, seq, col);
color3ubv_from_seq(scene, seq, background_col);
-
+
+ if (seq->flag & SEQ_MUTE) {
+ background_col[3] = 128;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else {
+ background_col[3] = 255;
+ }
+
+ if (seq->flag & SELECT) {
+ UI_GetColorPtrShade3ubv(background_col, background_col, -50);
+ }
+
+ immUniformColor4ubv(background_col);
+
/* draw the main strip body */
if (is_single_image) { /* single image */
- draw_shadedstrip(seq, background_col,
- BKE_sequence_tx_get_final_left(seq, false), y1,
- BKE_sequence_tx_get_final_right(seq, false), y2);
+ immRectf(pos, BKE_sequence_tx_get_final_left(seq, false), y1,
+ BKE_sequence_tx_get_final_right(seq, false), y2);
}
else { /* normal operation */
- draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
+ immRectf(pos, x1, y1, x2, y2);
+ }
+
+ if (seq->flag & SEQ_MUTE) {
+ glDisable(GL_BLEND);
}
if (!is_single_image) {
if ((sseq->draw_flag & SEQ_DRAW_OFFSET_EXT) || (seq == special_seq_update)) {
- draw_sequence_extensions(scene, ar, seq);
+ draw_sequence_extensions(scene, ar, seq, pos);
}
}
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
- draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
-
- /* draw the strip outline */
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE, pos);
+ draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE, pos);
+
x1 = seq->startdisp;
x2 = seq->enddisp;
/* draw sound wave */
if (seq->type == SEQ_TYPE_SOUND_RAM) {
if (!(sseq->flag & SEQ_NO_WAVEFORMS)) {
- drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+ drawseqwave(v2d, C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx, pos);
}
}
+ immUnbindProgram();
+
/* draw lock */
if (seq->flag & SEQ_LOCK) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
glEnable(GL_BLEND);
- /* light stripes */
- glColor4ub(255, 255, 255, 32);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES);
- glRectf(x1, y1, x2, y2);
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+ immUniform4f("color1", 1.0f, 1.0f, 1.0f, 0.125f);
+ immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.125f);
+ immUniform1i("size1", 8);
+ immUniform1i("size2", 8);
- /* dark stripes */
- glColor4ub(0, 0, 0, 32);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP);
- glRectf(x1, y1, x2, y2);
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
glDisable(GL_BLEND);
}
if (!BKE_sequence_is_valid_check(seq)) {
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
+ glEnable(GL_BLEND);
- /* panic! */
- glColor4ub(255, 0, 0, 255);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_DIAG_STRIPES);
- glRectf(x1, y1, x2, y2);
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immUniform4f("color1", 1.0f, 0.0f, 0.0f, 1.0f);
+ immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f);
+ immUniform1i("size1", 8);
+ immUniform1i("size2", 8);
+
+ immRectf(pos, x1, y1, x2, y2);
+
+ immUnbindProgram();
+
+ glDisable(GL_BLEND);
}
color3ubv_from_seq(scene, seq, col);
+
+ /* draw the strip outline */
+ color3ubv_from_seq(scene, seq, col);
if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
if (seq->flag & SEQ_OVERLAP) {
col[0] = 255; col[1] = col[2] = 40;
@@ -852,19 +828,27 @@ static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, AReg
drawmeta_contents(scene, seq, x1, y1, x2, y2);
}
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+ /* TODO: add back stippled line for muted strips? */
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
if (seq->flag & SEQ_MUTE) {
- glEnable(GL_LINE_STIPPLE);
- glLineStipple(1, 0x8888);
+ col[3] = 96;
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ immUniformColor4ubv(col);
+ }
+ else {
+ immUniformColor3ubv(col);
}
- rgb_uchar_to_float(fcol, col);
+ imm_draw_line_box(pos, x1, y1, x2, y2); /* outline */
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, x1, y1, x2, y2, 0.0, 0.1, 0.0, fcol);
+ immUnbindProgram();
- if (seq->flag & SEQ_MUTE) {
- glDisable(GL_LINE_STIPPLE);
- }
-
/* calculate if seq is long enough to print a name */
x1 = seq->startdisp + handsize_clamped;
x2 = seq->enddisp - handsize_clamped;
@@ -1050,8 +1034,7 @@ static void sequencer_draw_borders(const SpaceSeq *sseq, const View2D *v2d, cons
/* border */
setlinestyle(3);
- VertexFormat *format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_BACK);
@@ -1090,11 +1073,7 @@ static void sequencer_draw_background(
/* only draw alpha for main buffer */
if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
if ((sseq->flag & SEQ_USE_ALPHA) && !draw_overlay) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ imm_draw_checker_box(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
}
}
}
@@ -1138,9 +1117,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
glClear(GL_COLOR_BUFFER_BIT);
}
- /* without this colors can flicker from previous opengl state */
- glColor4ub(255, 255, 255, 255);
-
/* only initialize the preview if a render is in progress */
if (G.is_rendering)
return;
@@ -1155,15 +1131,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
if ((ibuf == NULL) ||
(ibuf->rect == NULL && ibuf->rect_float == NULL))
{
- /* gpencil can also be drawn without a valid imbuf */
- if ((draw_gpencil && is_imbuf) && !draw_overlay) {
- sequencer_display_size(scene, sseq, viewrect);
+ sequencer_display_size(scene, sseq, viewrect);
- sequencer_draw_background(sseq, v2d, viewrect, false);
- sequencer_draw_borders(sseq, v2d, scene);
+ sequencer_draw_background(sseq, v2d, viewrect, false);
+ sequencer_draw_borders(sseq, v2d, scene);
+ /* gpencil can also be drawn without a valid imbuf */
+ if ((draw_gpencil && is_imbuf) && !draw_overlay) {
sequencer_draw_gpencil(C);
}
+
return;
}
@@ -1232,6 +1209,11 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
sequencer_draw_background(sseq, v2d, viewrect, draw_overlay);
}
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+
if (scope) {
IMB_freeImBuf(ibuf);
ibuf = scope;
@@ -1304,9 +1286,12 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
}
- glColor4f(1.0, 1.0, 1.0, 1.0);
+ if (draw_backdrop) {
+ /* XXX: need to load identity projection too? */
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ }
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
glGenTextures(1, (GLuint *)&texid);
glBindTexture(GL_TEXTURE_2D, texid);
@@ -1319,15 +1304,15 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
- if (draw_backdrop) {
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- }
- glBegin(GL_QUADS);
+ VertexFormat *imm_format = immVertexFormat();
+ unsigned int pos = add_attrib(imm_format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int texCoord = add_attrib(imm_format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_COLOR);
+ immUniform4f("color", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1i("image", GL_TEXTURE0);
+
+ immBegin(GL_QUADS, 4);
if (draw_overlay) {
if (sseq->overlay_type == SEQ_DRAW_OVERLAY_RECT) {
@@ -1337,16 +1322,30 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
tot_clip.xmax = v2d->tot.xmin + (fabsf(BLI_rctf_size_x(&v2d->tot)) * scene->ed->over_border.xmax);
tot_clip.ymax = v2d->tot.ymin + (fabsf(BLI_rctf_size_y(&v2d->tot)) * scene->ed->over_border.ymax);
- glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmin, tot_clip.ymin);
- glTexCoord2f(scene->ed->over_border.xmin, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmin, tot_clip.ymax);
- glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymax); glVertex2f(tot_clip.xmax, tot_clip.ymax);
- glTexCoord2f(scene->ed->over_border.xmax, scene->ed->over_border.ymin); glVertex2f(tot_clip.xmax, tot_clip.ymin);
+ immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymin);
+ immVertex2f(pos, tot_clip.xmin, tot_clip.ymin);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmin, scene->ed->over_border.ymax);
+ immVertex2f(pos, tot_clip.xmin, tot_clip.ymax);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymax);
+ immVertex2f(pos, tot_clip.xmax, tot_clip.ymax);
+
+ immAttrib2f(texCoord, scene->ed->over_border.xmax, scene->ed->over_border.ymin);
+ immVertex2f(pos, tot_clip.xmax, tot_clip.ymin);
}
else if (sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
- glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin);
}
}
else if (draw_backdrop) {
@@ -1365,25 +1364,44 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
imagey = aspect / image_aspect;
}
- glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, -imagex, -imagey);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, -imagex, imagey);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, imagex, imagey);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, imagex, -imagey);
}
else {
draw_metadata = ((sseq->flag & SEQ_SHOW_METADATA) != 0);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymax);
- glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
+ immAttrib2f(texCoord, 0.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymin);
+
+ immAttrib2f(texCoord, 0.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmin, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 1.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymax);
+
+ immAttrib2f(texCoord, 1.0f, 0.0f);
+ immVertex2f(pos, v2d->tot.xmax, v2d->tot.ymin);
}
- glEnd();
+
+ immEnd();
glBindTexture(GL_TEXTURE_2D, 0);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
+
+ immUnbindProgram();
+
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA) {
glDisable(GL_BLEND);
+ }
+
glDeleteTextures(1, &texid);
if (glsl_used)
@@ -1400,10 +1418,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
}
if (draw_backdrop) {
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
+ gpuPopMatrix();
return;
}
@@ -1477,42 +1492,42 @@ void drawprefetchseqspace(Scene *scene, ARegion *UNUSED(ar), SpaceSeq *sseq)
static void draw_seq_backdrop(View2D *v2d)
{
int i;
-
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* darker gray overlay over the view backdrop */
- UI_ThemeColorShade(TH_BACK, -20);
- glRectf(v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
+ immUniformThemeColorShade(TH_BACK, -20);
+ immRectf(pos, v2d->cur.xmin, -1.0, v2d->cur.xmax, 1.0);
/* Alternating horizontal stripes */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
- glBegin(GL_QUADS);
while (i < v2d->cur.ymax) {
- if (((int)i) & 1)
- UI_ThemeColorShade(TH_BACK, -15);
- else
- UI_ThemeColorShade(TH_BACK, -25);
-
- glVertex2f(v2d->cur.xmax, i);
- glVertex2f(v2d->cur.xmin, i);
- glVertex2f(v2d->cur.xmin, i + 1);
- glVertex2f(v2d->cur.xmax, i + 1);
+ if (i & 1) {
+ immUniformThemeColorShade(TH_BACK, -15);
+ }
+ else {
+ immUniformThemeColorShade(TH_BACK, -25);
+ }
- i += 1.0;
+ immRectf(pos, v2d->cur.xmin, i, v2d->cur.xmax, i + 1);
+
+ i++;
}
- glEnd();
-
+
/* Darker lines separating the horizontal bands */
i = max_ii(1, ((int)v2d->cur.ymin) - 1);
- UI_ThemeColor(TH_GRID);
-
- glBegin(GL_LINES);
- while (i < v2d->cur.ymax) {
- glVertex2f(v2d->cur.xmax, i);
- glVertex2f(v2d->cur.xmin, i);
-
- i += 1.0;
+ int line_ct = (int)v2d->cur.ymax - i + 1;
+ immUniformThemeColor(TH_GRID);
+ immBegin(GL_LINES, line_ct * 2);
+ while (line_ct--) {
+ immVertex2f(pos, v2d->cur.xmax, i);
+ immVertex2f(pos, v2d->cur.xmin, i);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* draw the contents of the sequencer strips view */
@@ -1528,7 +1543,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
/* loop through twice, first unselected, then selected */
for (j = 0; j < 2; j++) {
Sequence *seq;
- int outline_tint = (j) ? -60 : -150; /* highlighting around strip edges indicating selection */
+ int outline_tint = (j) ? 40 : -40; /* highlighting around strip edges indicating selection */
/* loop through strips, checking for those that are visible */
for (seq = ed->seqbasep->first; seq; seq = seq->next) {
@@ -1556,8 +1571,15 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
if (special_seq_update) {
const Sequence *seq = special_seq_update;
glEnable(GL_BLEND);
- glColor4ub(255, 255, 255, 48);
- glRectf(seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4ub(255, 255, 255, 48);
+ immRectf(pos, seq->startdisp, seq->machine + SEQ_STRIP_OFSBOTTOM, seq->enddisp, seq->machine + SEQ_STRIP_OFSTOP);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
}
@@ -1569,36 +1591,56 @@ static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
const int frame_end = PEFRA + 1;
glEnable(GL_BLEND);
-
+
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw darkened area outside of active timeline
* frame range used is preview range or scene range */
- UI_ThemeColorShadeAlpha(TH_BACK, -25, -100);
+ immUniformThemeColorShadeAlpha(TH_BACK, -25, -100);
if (frame_sta < frame_end) {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
- glRectf((float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, (float)frame_sta, v2d->cur.ymax);
+ immRectf(pos, (float)frame_end, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
else {
- glRectf(v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
+ immRectf(pos, v2d->cur.xmin, v2d->cur.ymin, v2d->cur.xmax, v2d->cur.ymax);
}
- UI_ThemeColorShade(TH_BACK, -60);
+ immUniformThemeColorShade(TH_BACK, -60);
+
/* thin lines where the actual frames are */
- fdrawline(frame_sta, v2d->cur.ymin, frame_sta, v2d->cur.ymax);
- fdrawline(frame_end, v2d->cur.ymin, frame_end, v2d->cur.ymax);
+ immBegin(GL_LINES, 4);
+
+ immVertex2f(pos, frame_sta, v2d->cur.ymin);
+ immVertex2f(pos, frame_sta, v2d->cur.ymax);
+
+ immVertex2f(pos, frame_end, v2d->cur.ymin);
+ immVertex2f(pos, frame_end, v2d->cur.ymax);
+
+ immEnd();
if (ed && !BLI_listbase_is_empty(&ed->metastack)) {
MetaStack *ms = ed->metastack.last;
- glColor4ub(255, 255, 255, 8);
- glRectf(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immUniformColor4ub(255, 255, 255, 8);
+ immRectf(pos, ms->disp_range[0], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+
+ immUniformThemeColorShade(TH_BACK, -40);
+
+ immBegin(GL_LINES, 4);
- UI_ThemeColorShade(TH_BACK, -40);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[0], v2d->cur.ymax);
- fdrawline(ms->disp_range[0], v2d->cur.ymin, ms->disp_range[0], v2d->cur.ymax);
- fdrawline(ms->disp_range[1], v2d->cur.ymin, ms->disp_range[1], v2d->cur.ymax);
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymin);
+ immVertex2f(pos, ms->disp_range[1], v2d->cur.ymax);
+
+ immEnd();
}
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
@@ -1673,16 +1715,20 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
/* overlap playhead */
if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ? scene->ed->over_cfra : scene->r.cfra + scene->ed->over_ofs;
- glColor3f(0.2, 0.2, 0.2);
- // glRectf(cfra_over, v2d->cur.ymin, scene->ed->over_ofs + scene->r.cfra + 1, v2d->cur.ymax);
- glBegin(GL_LINES);
- glVertex2f(cfra_over, v2d->cur.ymin);
- glVertex2f(cfra_over, v2d->cur.ymax);
- glEnd();
+ unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor3f(0.2, 0.2, 0.2);
+ immBegin(GL_LINES, 2);
+ immVertex2f(pos, cfra_over, v2d->cur.ymin);
+ immVertex2f(pos, cfra_over, v2d->cur.ymax);
+ immEnd();
+
+ immUnbindProgram();
}
-
+
/* callback */
ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 8ae89941bdb..8963eb760ce 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -1256,7 +1256,6 @@ typedef struct SlipData {
int num_seq;
bool slow;
int slow_offset; /* offset at the point where offset was turned on */
- void *draw_handle;
NumInput num_input;
} SlipData;
@@ -1291,21 +1290,6 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
seq->len = ts->len;
}
-static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
-{
- Scene *scene = CTX_data_scene(C);
- SlipData *td = data;
- int i;
-
- for (i = 0; i < td->num_seq; i++) {
- Sequence *seq = td->seq_array[i];
-
- if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
- draw_sequence_extensions(scene, ar, seq);
- }
- }
-}
-
static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
{
Sequence *seq;
@@ -1354,7 +1338,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
SlipData *data;
Scene *scene = CTX_data_scene(C);
Editing *ed = BKE_sequencer_editing_get(scene, false);
- ARegion *ar = CTX_wm_region(C);
float mouseloc[2];
int num_seq, i;
View2D *v2d = UI_view2d_fromcontext(C);
@@ -1384,8 +1367,6 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
transseq_backup(data->ts + i, data->seq_array[i]);
}
- data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
-
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
copy_v2_v2_int(data->init_mouse, event->mval);
@@ -1527,7 +1508,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
Scene *scene = CTX_data_scene(C);
SlipData *data = (SlipData *)op->customdata;
ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
const bool has_numInput = hasNumInput(&data->num_input);
bool handled = true;
@@ -1585,7 +1565,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
case RETKEY:
case SPACEKEY:
{
- ED_region_draw_cb_exit(ar->type, data->draw_handle);
MEM_freeN(data->seq_array);
MEM_freeN(data->trim);
MEM_freeN(data->ts);
@@ -1614,8 +1593,6 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
BKE_sequence_calc(scene, seq);
}
- ED_region_draw_cb_exit(ar->type, data->draw_handle);
-
MEM_freeN(data->seq_array);
MEM_freeN(data->ts);
MEM_freeN(data->trim);
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 730cc117287..7ce2f73cbef 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -56,8 +56,6 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
-void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
-void draw_sequence_extensions(struct Scene *scene, struct ARegion *ar, struct Sequence *seq);
void sequencer_special_update_set(Sequence *seq);
diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c
index 30b607e063d..b6d71b8ccf9 100644
--- a/source/blender/editors/space_text/text_draw.c
+++ b/source/blender/editors/space_text/text_draw.c
@@ -49,6 +49,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -123,38 +125,38 @@ static void txt_format_text(SpaceText *st)
#endif
/* Sets the current drawing color based on the format character specified */
-static void format_draw_color(char formatchar)
+static void format_draw_color(const TextDrawContext *tdc, char formatchar)
{
switch (formatchar) {
case FMT_TYPE_WHITESPACE:
break;
case FMT_TYPE_SYMBOL:
- UI_ThemeColor(TH_SYNTAX_S);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_S);
break;
case FMT_TYPE_COMMENT:
- UI_ThemeColor(TH_SYNTAX_C);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_C);
break;
case FMT_TYPE_NUMERAL:
- UI_ThemeColor(TH_SYNTAX_N);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_N);
break;
case FMT_TYPE_STRING:
- UI_ThemeColor(TH_SYNTAX_L);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_L);
break;
case FMT_TYPE_DIRECTIVE:
- UI_ThemeColor(TH_SYNTAX_D);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_D);
break;
case FMT_TYPE_SPECIAL:
- UI_ThemeColor(TH_SYNTAX_V);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_V);
break;
case FMT_TYPE_RESERVED:
- UI_ThemeColor(TH_SYNTAX_R);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_R);
break;
case FMT_TYPE_KEYWORD:
- UI_ThemeColor(TH_SYNTAX_B);
+ UI_FontThemeColor(tdc->font_id, TH_SYNTAX_B);
break;
case FMT_TYPE_DEFAULT:
default:
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(tdc->font_id, TH_TEXT);
break;
}
}
@@ -429,7 +431,7 @@ static int text_draw_wrapped(
/* Draw the visible portion of text on the overshot line */
for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
}
x += text_font_draw_character_utf8(tdc, x, y, str + ma);
fpos++;
@@ -452,7 +454,7 @@ static int text_draw_wrapped(
/* Draw the remaining text */
for (a = fstart, ma = mstart; str[ma] && y > clip_min_y; a++, ma += BLI_str_utf8_size_safe(str + ma)) {
if (use_syntax) {
- if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]);
+ if (fmt_prev != format[a]) format_draw_color(tdc, fmt_prev = format[a]);
}
x += text_font_draw_character_utf8(tdc, x, y, str + ma);
@@ -505,7 +507,7 @@ static void text_draw(
char fmt_prev = 0xff;
for (a = 0; a < amount; a++) {
- if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]);
+ if (format[a] != fmt_prev) format_draw_color(tdc, fmt_prev = format[a]);
x += text_font_draw_character_utf8(tdc, x, y, in + str_shift);
str_shift += BLI_str_utf8_size_safe(in + str_shift);
}
@@ -908,9 +910,13 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
uiWidgetColors wcol = btheme->tui.wcol_scroll;
float col[4];
float rad;
-
- UI_ThemeColor(TH_BACK);
- glRecti(back->xmin, back->ymin, back->xmax, back->ymax);
+
+ /* background so highlights don't go behind the scrollbar */
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, back->xmin, back->ymin, back->xmax, back->ymax);
+ immUnbindProgram();
UI_draw_widget_scroll(&wcol, scroll, &st->txtbar, (st->flags & ST_SCROLL_SELECT) ? UI_SCROLL_PRESSED : 0);
@@ -925,6 +931,7 @@ static void draw_textscroll(const SpaceText *st, rcti *scroll, rcti *back)
/*********************** draw documentation *******************************/
+#if 0
static void draw_documentation(const SpaceText *st, ARegion *ar)
{
TextDrawContext tdc = {0};
@@ -961,26 +968,32 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
boxh = (DOC_HEIGHT + 1) * (st->lheight_dpi + TXT_LINE_SPACING);
/* Draw panel */
- UI_ThemeColor(TH_BACK);
- glRecti(x, y, x + boxw, y - boxh);
- UI_ThemeColor(TH_SHADE1);
- glBegin(GL_LINE_LOOP);
- glVertex2i(x, y);
- glVertex2i(x + boxw, y);
- glVertex2i(x + boxw, y - boxh);
- glVertex2i(x, y - boxh);
- glEnd();
- glBegin(GL_LINE_LOOP);
- glVertex2i(x + boxw - 10, y - 7);
- glVertex2i(x + boxw - 4, y - 7);
- glVertex2i(x + boxw - 7, y - 2);
- glEnd();
- glBegin(GL_LINE_LOOP);
- glVertex2i(x + boxw - 10, y - boxh + 7);
- glVertex2i(x + boxw - 4, y - boxh + 7);
- glVertex2i(x + boxw - 7, y - boxh + 2);
- glEnd();
- UI_ThemeColor(TH_TEXT);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_BACK);
+ immRecti(pos, x, y, x + boxw, y - boxh);
+ immUniformThemeColor(TH_SHADE1);
+ immBegin(GL_LINE_LOOP, 4);
+ immVertex2i(pos, x, y);
+ immVertex2i(pos, x + boxw, y);
+ immVertex2i(pos, x + boxw, y - boxh);
+ immVertex2i(pos, x, y - boxh);
+ immEnd();
+ immBegin(GL_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - 7);
+ immVertex2i(pos, x + boxw - 4, y - 7);
+ immVertex2i(pos, x + boxw - 7, y - 2);
+ immEnd();
+ immBegin(GL_LINE_LOOP, 3);
+ immVertex2i(pos, x + boxw - 10, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 4, y - boxh + 7);
+ immVertex2i(pos, x + boxw - 7, y - boxh + 2);
+ immEnd();
+
+ immUnbindProgram();
+
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
i = 0; br = DOC_WIDTH; lines = 0; // XXX -doc_scroll;
for (p = docs; *p; p++) {
@@ -1007,12 +1020,8 @@ static void draw_documentation(const SpaceText *st, ARegion *ar)
}
if (lines >= DOC_HEIGHT) break;
}
-
- if (0 /* XXX doc_scroll*/ /* > 0 && lines < DOC_HEIGHT */) {
- // XXX doc_scroll--;
- draw_documentation(st, ar);
- }
}
+#endif
/*********************** draw suggestion list *******************************/
@@ -1058,10 +1067,15 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/* not needed but stands out nicer */
UI_draw_box_shadow(220, x, y - boxh, x + boxw, y);
- UI_ThemeColor(TH_SHADE1);
- glRecti(x - 1, y + 1, x + boxw + 1, y - boxh - 1);
- UI_ThemeColorShade(TH_BACK, 16);
- glRecti(x, y, x + boxw, y - boxh);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_SHADE1);
+ immRecti(pos, x - 1, y + 1, x + boxw + 1, y - boxh - 1);
+ immUniformThemeColorShade(TH_BACK, 16);
+ immRecti(pos, x, y, x + boxw, y - boxh);
+
+ immUnbindProgram();
/* Set the top 'item' of the visible list */
for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ;
@@ -1076,11 +1090,16 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
w = st->cwidth * text_get_char_pos(st, str, len);
if (item == sel) {
- UI_ThemeColor(TH_SHADE2);
- glRecti(x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
+ unsigned int posi = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformThemeColor(TH_SHADE2);
+ immRecti(posi, x + margin_x, y - 3, x + margin_x + w, y + lheight - 3);
+
+ immUnbindProgram();
}
- format_draw_color(item->type);
+ format_draw_color(tdc, item->type);
text_draw(st, tdc, str, 0, 0, x + margin_x, y - 1, NULL);
if (item == last) break;
@@ -1089,42 +1108,57 @@ static void draw_suggestion_list(const SpaceText *st, const TextDrawContext *tdc
/*********************** draw cursor ************************/
-static void draw_cursor(SpaceText *st, ARegion *ar)
+static void draw_text_decoration(SpaceText *st, ARegion *ar)
{
Text *text = st->text;
int vcurl, vcurc, vsell, vselc, hidden = 0;
int x, y, w, i;
+ int offl, offc;
const int lheight = st->lheight_dpi + TXT_LINE_SPACING;
+ /* Convert to view space character coordinates to determine if cursor is hidden */
+ wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
+ vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
+ vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
+
+ if (vselc < 0) {
+ vselc = 0;
+ hidden = 1;
+ }
+
+ if (text->curl == text->sell && text->curc == text->selc && !st->line_hlight && hidden) {
+ /* Nothing to draw here */
+ return;
+ }
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* Draw the selection */
if (text->curl != text->sell || text->curc != text->selc) {
- int offl, offc;
/* Convert all to view space character coordinates */
wrap_offset(st, ar, text->curl, text->curc, &offl, &offc);
vcurl = txt_get_span(text->lines.first, text->curl) - st->top + offl;
vcurc = text_get_char_pos(st, text->curl->line, text->curc) - st->left + offc;
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
- vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
- vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
if (vcurc < 0) {
vcurc = 0;
}
- if (vselc < 0) {
- vselc = 0;
- hidden = 1;
- }
-
- UI_ThemeColor(TH_SHADE2);
+
+ immUniformThemeColor(TH_SHADE2);
+
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
y = ar->winy;
if (vcurl == vsell) {
y -= vcurl * lheight;
- if (vcurc < vselc)
- glRecti(x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
- else
- glRecti(x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
+
+ if (vcurc < vselc) {
+ immRecti(pos, x + vcurc * st->cwidth - 1, y, x + vselc * st->cwidth, y - lheight);
+ }
+ else {
+ immRecti(pos, x + vselc * st->cwidth - 1, y, x + vcurc * st->cwidth, y - lheight);
+ }
}
else {
int froml, fromc, tol, toc;
@@ -1140,35 +1174,24 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
y -= froml * lheight;
- glRecti(x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
+ immRecti(pos, x + fromc * st->cwidth - 1, y, ar->winx, y - lheight);
y -= lheight;
+
for (i = froml + 1; i < tol; i++) {
- glRecti(x - 4, y, ar->winx, y - lheight);
+ immRecti(pos, x - 4, y, ar->winx, y - lheight);
y -= lheight;
}
- glRecti(x - 4, y, x + toc * st->cwidth, y - lheight);
+ immRecti(pos, x - 4, y, x + toc * st->cwidth, y - lheight);
y -= lheight;
}
}
- else {
- int offl, offc;
- wrap_offset(st, ar, text->sell, text->selc, &offl, &offc);
- vsell = txt_get_span(text->lines.first, text->sell) - st->top + offl;
- vselc = text_get_char_pos(st, text->sell->line, text->selc) - st->left + offc;
-
- if (vselc < 0) {
- vselc = 0;
- hidden = 1;
- }
- }
if (st->line_hlight) {
int x1, x2, y1, y2;
if (st->wordwrap) {
int visible_lines = text_get_visible_lines(st, ar, text->sell->line);
- int offl, offc;
wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc);
@@ -1184,36 +1207,38 @@ static void draw_cursor(SpaceText *st, ARegion *ar)
x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x2 = x1 + ar->winx;
- glColor4ub(255, 255, 255, 32);
-
+ immUniformColor4ub(255, 255, 255, 32);
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
- glRecti(x1 - 4, y1, x2, y2);
+ immRecti(pos, x1 - 4, y1, x2, y2);
glDisable(GL_BLEND);
}
}
-
+
if (!hidden) {
/* Draw the cursor itself (we draw the sel. cursor as this is the leading edge) */
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
x += vselc * st->cwidth;
y = ar->winy - vsell * lheight;
-
+
+ immUniformThemeColor(TH_HILITE);
+
if (st->overwrite) {
char ch = text->sell->line[text->selc];
-
+
y += TXT_LINE_SPACING;
w = st->cwidth;
if (ch == '\t') w *= st->tabnumber - (vselc + st->left) % st->tabnumber;
-
- UI_ThemeColor(TH_HILITE);
- glRecti(x, y - lheight - 1, x + w, y - lheight + 1);
+
+ immRecti(pos, x, y - lheight - 1, x + w, y - lheight + 1);
}
else {
- UI_ThemeColor(TH_HILITE);
- glRecti(x - 1, y, x + 1, y - lheight);
+ immRecti(pos, x - 1, y, x + 1, y - lheight);
}
}
+
+ immUnbindProgram();
}
/******************* draw matching brackets *********************/
@@ -1314,7 +1339,7 @@ static void draw_brackets(const SpaceText *st, const TextDrawContext *tdc, ARegi
if (!endl || endc == -1)
return;
- UI_ThemeColor(TH_HILITE);
+ UI_FontThemeColor(tdc->font_id, TH_HILITE);
x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET;
y = ar->winy - st->lheight_dpi;
@@ -1419,8 +1444,11 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->showlinenrs) {
x = TXT_OFFSET + TEXTXLOC;
- UI_ThemeColor(TH_GRID);
- glRecti((TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_GRID);
+ immRecti(pos, (TXT_OFFSET - 12), 0, (TXT_OFFSET - 5) + TEXTXLOC, ar->winy - 2);
+ immUnbindProgram();
}
else {
st->linenrs_tot = 0; /* not used */
@@ -1429,11 +1457,11 @@ void draw_text_main(SpaceText *st, ARegion *ar)
y = ar->winy - st->lheight_dpi;
winx = ar->winx - TXT_SCROLL_WIDTH;
- /* draw cursor */
- draw_cursor(st, ar);
+ /* draw cursor, margin, selection and highlight */
+ draw_text_decoration(st, ar);
/* draw the text */
- UI_ThemeColor(TH_TEXT);
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
for (i = 0; y > clip_min_y && i < st->viewlines && tmp; i++, tmp = tmp->next) {
if (st->showsyntax && !tmp->format)
@@ -1441,16 +1469,20 @@ void draw_text_main(SpaceText *st, ARegion *ar)
if (st->showlinenrs && !wrap_skip) {
/* draw line number */
- if (tmp == text->curl)
- UI_ThemeColor(TH_HILITE);
- else
- UI_ThemeColor(TH_TEXT);
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_HILITE);
+ }
+ else {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
BLI_snprintf(linenr, sizeof(linenr), "%*d", st->linenrs_tot, i + linecount + 1);
/* itoa(i + linecount + 1, linenr, 10); */ /* not ansi-c :/ */
text_font_draw(&tdc, TXT_OFFSET - 7, y, linenr);
- UI_ThemeColor(TH_TEXT);
+ if (tmp == text->curl) {
+ UI_FontThemeColor(tdc.font_id, TH_TEXT);
+ }
}
if (st->wordwrap) {
@@ -1471,14 +1503,17 @@ void draw_text_main(SpaceText *st, ARegion *ar)
margin_column_x = x + st->cwidth * (st->margin_column - st->left);
if (margin_column_x >= x) {
- /* same color as line number background */
- UI_ThemeColor(TH_GRID);
-
setlinestyle(1);
- glBegin(GL_LINES);
- glVertex2i(margin_column_x, 0);
- glVertex2i(margin_column_x, ar->winy - 2);
- glEnd();
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* same color as line number background */
+ immUniformThemeColor(TH_GRID);
+ immBegin(GL_LINES, 2);
+ immVertex2i(pos, margin_column_x, 0);
+ immVertex2i(pos, margin_column_x, ar->winy - 2);
+ immEnd();
+ immUnbindProgram();
setlinestyle(0);
}
}
@@ -1486,7 +1521,7 @@ void draw_text_main(SpaceText *st, ARegion *ar)
/* draw other stuff */
draw_brackets(st, &tdc, ar);
draw_textscroll(st, &scroll, &back);
- draw_documentation(st, ar);
+ /* draw_documentation(st, ar); - No longer supported */
draw_suggestion_list(st, &tdc, ar);
text_font_end(&tdc);
diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c
index e9306c04cfa..17b30fd8bae 100644
--- a/source/blender/editors/space_time/space_time.c
+++ b/source/blender/editors/space_time/space_time.c
@@ -70,6 +70,7 @@
#include "ED_markers.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "time_intern.h"
@@ -118,7 +119,6 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
{
PTCacheID *pid;
ListBase pidlist;
- SpaceTimeCache *stc = stime->caches.first;
const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
float yoffs = 0.f;
@@ -127,12 +127,13 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* iterate over pointcaches on the active object,
* add spacetimecache and vertex array for each */
for (pid = pidlist.first; pid; pid = pid->next) {
- float col[4], *fp;
- int i, sta = pid->cache->startframe, end = pid->cache->endframe;
- int len = (end - sta + 1) * 4;
+ float col[4];
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -159,43 +160,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
if (pid->cache->cached_frames == NULL)
continue;
- /* make sure we have stc with correct array length */
- if (stc == NULL || MEM_allocN_len(stc->array) != len * 2 * sizeof(float)) {
- if (stc) {
- MEM_freeN(stc->array);
- }
- else {
- stc = MEM_callocN(sizeof(SpaceTimeCache), "spacetimecache");
- BLI_addtail(&stime->caches, stc);
- }
-
- stc->array = MEM_callocN(len * 2 * sizeof(float), "SpaceTimeCache array");
- }
-
- /* fill the vertex array with a quad for each cached frame */
- for (i = sta, fp = stc->array; i <= end; i++) {
- if (pid->cache->cached_frames[i - sta]) {
- fp[0] = (float)i - 0.5f;
- fp[1] = 0.0;
- fp += 2;
-
- fp[0] = (float)i - 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 1.0;
- fp += 2;
-
- fp[0] = (float)i + 0.5f;
- fp[1] = 0.0;
- fp += 2;
- }
- }
-
- glPushMatrix();
- glTranslatef(0.0, (float)V2D_SCROLL_HEIGHT + yoffs, 0.0);
- glScalef(1.0, cache_draw_height, 0.0);
+ gpuPushMatrix();
+ gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs);
+ gpuScale2f(1.0, cache_draw_height);
switch (pid->type) {
case PTCACHE_TYPE_SOFTBODY:
@@ -229,12 +196,15 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
BLI_assert(0);
break;
}
- glColor4fv(col);
-
+
+ int sta = pid->cache->startframe, end = pid->cache->endframe;
+ int len = (end - sta + 1) * 4;
+
glEnable(GL_BLEND);
-
- glRectf((float)sta, 0.0, (float)end, 1.0);
-
+
+ immUniformColor4fv(col);
+ immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
+
col[3] = 0.4f;
if (pid->cache->flag & PTCACHE_BAKED) {
col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
@@ -242,52 +212,35 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene)
else if (pid->cache->flag & PTCACHE_OUTDATED) {
col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
}
- glColor4fv(col);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, stc->array);
- glDrawArrays(GL_QUADS, 0, (fp - stc->array) / 2);
- glDisableClientState(GL_VERTEX_ARRAY);
-
- glDisable(GL_BLEND);
-
- glPopMatrix();
-
- yoffs += cache_draw_height;
- stc = stc->next;
- }
+ immUniformColor4fv(col);
- BLI_freelistN(&pidlist);
+ if (len > 0) {
+ immBeginAtMost(GL_QUADS, len);
- /* free excessive caches */
- while (stc) {
- SpaceTimeCache *tmp = stc->next;
- BLI_remlink(&stime->caches, stc);
- MEM_freeN(stc->array);
- MEM_freeN(stc);
- stc = tmp;
- }
-}
+ /* draw a quad for each cached frame */
+ for (int i = sta; i <= end; i++) {
+ if (pid->cache->cached_frames[i - sta]) {
+ immVertex2f(pos, (float)i - 0.5f, 0.0f);
+ immVertex2f(pos, (float)i - 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 0.0f);
+ }
+ }
-static void time_cache_free(SpaceTime *stime)
-{
- SpaceTimeCache *stc;
-
- for (stc = stime->caches.first; stc; stc = stc->next) {
- if (stc->array) {
- MEM_freeN(stc->array);
- stc->array = NULL;
+ immEnd();
}
+
+ glDisable(GL_BLEND);
+
+ gpuPopMatrix();
+
+ yoffs += cache_draw_height;
}
-
- BLI_freelistN(&stime->caches);
-}
-static void time_cache_refresh(SpaceTime *stime)
-{
- /* Free previous caches to indicate full refresh */
- time_cache_free(stime);
+ immUnbindProgram();
+
+ BLI_freelistN(&pidlist);
}
/* helper function - find actkeycolumn that occurs on cframe, or the nearest one if not found */
@@ -391,7 +344,7 @@ static void time_draw_idblock_keyframes(View2D *v2d, ID *id, short onlysel, cons
BLI_dlrbTree_free(&keys);
}
-static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, bool onlysel, const unsigned char color[3])
+static void time_draw_caches_keyframes(Main *bmain, SceneLayer *sl, View2D *v2d, bool onlysel, const unsigned char color[3])
{
CacheFile *cache_file;
@@ -402,7 +355,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
cache_file->draw_flag &= ~CACHEFILE_KEYFRAME_DRAWN;
}
- for (BaseLegacy *base = scene->base.first; base; base = base->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
@@ -445,6 +398,7 @@ static void time_draw_caches_keyframes(Main *bmain, Scene *scene, View2D *v2d, b
static void time_draw_keyframes(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = CTX_data_active_object(C);
View2D *v2d = &ar->v2d;
bool onlysel = ((scene->flag & SCE_KEYS_NO_SELONLY) == 0);
@@ -455,7 +409,7 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
/* draw cache files keyframes (if available) */
UI_GetThemeColor3ubv(TH_TIME_KEYFRAME, color);
- time_draw_caches_keyframes(CTX_data_main(C), scene, v2d, onlysel, color);
+ time_draw_caches_keyframes(CTX_data_main(C), sl, v2d, onlysel, color);
/* draw grease pencil keyframes (if available) */
UI_GetThemeColor3ubv(TH_TIME_GP_KEYFRAME, color);
@@ -511,16 +465,6 @@ static void time_draw_keyframes(const bContext *C, ARegion *ar)
/* ---------------- */
-static void time_refresh(const bContext *UNUSED(C), ScrArea *sa)
-{
- /* find the main timeline region and refresh cache display*/
- ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
- if (ar) {
- SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
- time_cache_refresh(stime);
- }
-}
-
/* editor level listener */
static void time_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
{
@@ -792,13 +736,6 @@ static SpaceLink *time_new(const bContext *C)
return (SpaceLink *)stime;
}
-/* not spacelink itself */
-static void time_free(SpaceLink *sl)
-{
- SpaceTime *stime = (SpaceTime *)sl;
-
- time_cache_free(stime);
-}
/* spacetype; init callback in ED_area_initialize() */
/* init is called to (re)initialize an existing editor (file read, screen changes) */
/* validate spacedata, add own area level handlers */
@@ -806,8 +743,6 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceTime *stime = (SpaceTime *)sa->spacedata.first;
- time_cache_free(stime);
-
/* enable all cache display */
stime->cache_display |= TIME_CACHE_DISPLAY;
stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
@@ -836,13 +771,11 @@ void ED_spacetype_time(void)
strncpy(st->name, "Timeline", BKE_ST_MAXNAME);
st->new = time_new;
- st->free = time_free;
st->init = time_init;
st->duplicate = time_duplicate;
st->operatortypes = time_operatortypes;
st->keymap = NULL;
st->listener = time_listener;
- st->refresh = time_refresh;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype time region");
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index fd9d995dff1..c99de124fc0 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -25,6 +25,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../draw
../../gpu
../../imbuf
../../makesdna
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index 505ed1fdd3a..7ab2b4ec3a4 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -49,9 +49,8 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BIF_gl.h"
-
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_keyframes_draw.h"
@@ -73,8 +72,8 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix3D(rv3d->viewmat);
}
/* set color
@@ -435,5 +434,5 @@ void draw_motion_path_instance(Scene *scene,
void draw_motion_paths_cleanup(View3D *v3d)
{
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- glPopMatrix();
+ gpuPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c
index a7bff0a8301..9d555cf7907 100644
--- a/source/blender/editors/space_view3d/drawarmature.c
+++ b/source/blender/editors/space_view3d/drawarmature.c
@@ -55,8 +55,6 @@
#include "BKE_nla.h"
#include "BKE_curve.h"
-
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "ED_armature.h"
@@ -64,6 +62,7 @@
#include "GPU_basic_shader.h"
#include "GPU_batch.h"
+#include "GPU_immediate.h"
#include "GPU_matrix.h"
#include "UI_resources.h"
@@ -77,8 +76,9 @@
/* global here is reset before drawing each bone */
static ThemeWireColor *bcolor = NULL;
static float fcolor[4] = {0.0f};
+static bool flat_color;
-/* values of colCode for set_pchan_glcolor */
+/* values of colCode for set_pchan_color */
enum {
PCHAN_COLOR_NORMAL = 0, /* normal drawing */
PCHAN_COLOR_SOLID, /* specific case where "solid" color is needed */
@@ -131,7 +131,7 @@ static void set_pchan_colorset(Object *ob, bPoseChannel *pchan)
}
}
-/* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
+/* This function is for brightening/darkening a given color (like UI_GetThemeColorShade3ubv()) */
static void cp_shade_color3ub(unsigned char cp[3], const int offset)
{
int r, g, b;
@@ -149,9 +149,8 @@ static void cp_shade_color3ub(unsigned char cp[3], const int offset)
}
/* This function sets the gl-color for coloring a certain bone (based on bcolor) */
-static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
+static bool set_pchan_color(short colCode, int boneflag, short constflag)
{
- /* TODO remove glColor/UI_ThemeColor functions when no longer needed */
switch (colCode) {
case PCHAN_COLOR_NORMAL:
{
@@ -173,24 +172,19 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
cp_shade_color3ub(cp, -50);
}
- glColor3ubv(cp);
rgb_uchar_to_float(fcolor, cp);
}
else {
if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
- UI_ThemeColor(TH_BONE_POSE_ACTIVE);
UI_GetThemeColor4fv(TH_BONE_POSE_ACTIVE, fcolor);
}
else if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
UI_GetThemeColorBlendShade4fv(TH_WIRE, TH_BONE_POSE, 0.15f, 0, fcolor);
}
else if (boneflag & BONE_SELECTED) {
- UI_ThemeColor(TH_BONE_POSE);
UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
}
else {
- UI_ThemeColor(TH_WIRE);
UI_GetThemeColor4fv(TH_WIRE, fcolor);
}
}
@@ -200,11 +194,9 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
case PCHAN_COLOR_SOLID:
{
if (bcolor) {
- glColor3ubv((unsigned char *)bcolor->solid);
rgb_uchar_to_float(fcolor, (unsigned char *)bcolor->solid);
}
else {
- UI_ThemeColor(TH_BONE_SOLID);
UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
@@ -219,7 +211,6 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
else if (constflag & PCHAN_HAS_SPLINEIK) rgba_char_args_set((char *)cp, 200, 255, 0, 80);
else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 80);
- glColor4ubv(cp);
rgba_uchar_to_float(fcolor, cp);
return true;
@@ -241,20 +232,16 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
copy_v3_v3_char((char *)cp, bcolor->solid);
}
- glColor3ubv(cp);
rgb_uchar_to_float(fcolor, cp);
}
else {
if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorShade(TH_BONE_POSE, 40);
UI_GetThemeColorShade4fv(TH_BONE_POSE, 40, fcolor);
}
else if (boneflag & BONE_SELECTED) {
- UI_ThemeColor(TH_BONE_POSE);
UI_GetThemeColor4fv(TH_BONE_POSE, fcolor);
}
else {
- UI_ThemeColor(TH_BONE_SOLID);
UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
}
@@ -279,20 +266,16 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
cp_shade_color3ub(cp, -30);
}
- glColor3ubv(cp);
rgb_uchar_to_float(fcolor, cp);
}
else {
if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorShade(TH_BONE_POSE, 10);
UI_GetThemeColorShade4fv(TH_BONE_POSE, 10, fcolor);
}
else if (boneflag & BONE_SELECTED) {
- UI_ThemeColorShade(TH_BONE_POSE, -30);
UI_GetThemeColorShade4fv(TH_BONE_POSE, -30, fcolor);
}
else {
- UI_ThemeColorShade(TH_BONE_SOLID, -30);
UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
}
}
@@ -309,18 +292,15 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
else if (constflag & PCHAN_HAS_CONST) rgba_char_args_set((char *)cp, 0, 255, 120, 255);
else if (constflag) UI_GetThemeColor4ubv(TH_BONE_POSE, cp); /* PCHAN_HAS_ACTION */
- glColor4ubv(cp);
rgb_uchar_to_float(fcolor, cp);
}
else {
if (bcolor) {
const char *cp = bcolor->solid;
- glColor4ub(cp[0], cp[1], cp[2], 204);
rgb_uchar_to_float(fcolor, (unsigned char *)cp);
fcolor[3] = 204.f / 255.f;
}
else {
- UI_ThemeColorShade(TH_BACK, -30);
UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
}
}
@@ -332,29 +312,35 @@ static bool set_pchan_glColor(short colCode, int boneflag, short constflag)
return false;
}
-static void set_ebone_glColor(const unsigned int boneflag)
+static void set_ebone_color(const unsigned int boneflag)
{
- /* TODO remove glColor/UI_ThemeColor functions when no longer needed */
if ((boneflag & BONE_DRAW_ACTIVE) && (boneflag & BONE_SELECTED)) {
- UI_ThemeColor(TH_EDGE_SELECT);
UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
}
else if (boneflag & BONE_DRAW_ACTIVE) {
- UI_ThemeColorBlend(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f); /* unselected active */
UI_GetThemeColorBlendShade4fv(TH_WIRE_EDIT, TH_EDGE_SELECT, 0.15f, 0, fcolor);
}
else if (boneflag & BONE_SELECTED) {
- UI_ThemeColorShade(TH_EDGE_SELECT, -20);
UI_GetThemeColorShade4fv(TH_EDGE_SELECT, -20, fcolor);
}
else {
- UI_ThemeColor(TH_WIRE_EDIT);
UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
}
}
/* *************** Armature drawing, helper calls for parts ******************* */
+static void add_solid_flat_triangle(VertexBuffer *vbo, unsigned int *vertex, unsigned int pos, unsigned int nor,
+ const float p1[3], const float p2[3], const float p3[3], const float n[3])
+{
+ setAttrib(vbo, nor, *vertex, n);
+ setAttrib(vbo, pos, (*vertex)++, p1);
+ setAttrib(vbo, nor, *vertex, n);
+ setAttrib(vbo, pos, (*vertex)++, p2);
+ setAttrib(vbo, nor, *vertex, n);
+ setAttrib(vbo, pos, (*vertex)++, p3);
+}
+
/* half the cube, in Y */
static const float cube_vert[8][3] = {
{-1.0, 0.0, -1.0},
@@ -375,53 +361,72 @@ static const float cube_wire[24] = {
static void drawsolidcube_size(float xsize, float ysize, float zsize)
{
- static GLuint displist = 0;
- float n[3] = {0.0f};
-
- glScalef(xsize, ysize, zsize);
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {{0}};
+ static Batch batch = {{0}};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
- if (displist == 0) {
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
+ if (format.attrib_ct == 0) {
+ unsigned int i = 0;
+ float n[3] = {0.0f};
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int nor = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 36);
- glBegin(GL_QUADS);
n[0] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[3]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[1], cube_vert[2], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[3], cube_vert[0], n);
n[0] = 0;
n[1] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[1]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[4], cube_vert[5], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[5], cube_vert[1], cube_vert[0], n);
n[1] = 0;
n[0] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[5]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[4], cube_vert[7], cube_vert[6], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[5], cube_vert[4], n);
n[0] = 0;
n[1] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[3]); glVertex3fv(cube_vert[2]); glVertex3fv(cube_vert[6]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[3], cube_vert[2], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[2], cube_vert[6], cube_vert[7], n);
n[1] = 0;
n[2] = 1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[1]); glVertex3fv(cube_vert[5]); glVertex3fv(cube_vert[6]); glVertex3fv(cube_vert[2]);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[1], cube_vert[5], cube_vert[6], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[6], cube_vert[2], cube_vert[1], n);
n[2] = -1.0;
- glNormal3fv(n);
- glVertex3fv(cube_vert[7]); glVertex3fv(cube_vert[4]); glVertex3fv(cube_vert[0]); glVertex3fv(cube_vert[3]);
- glEnd();
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[7], cube_vert[4], cube_vert[0], n);
+ add_solid_flat_triangle(&vbo, &i, pos, nor, cube_vert[0], cube_vert[3], cube_vert[7], n);
+
+ Batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+ }
+
+ gpuPushMatrix();
+ gpuScale3f(xsize, ysize, zsize);
- glEndList();
+ if (flat_color) {
+ Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
+ else {
+ /* TODO replace with good default lighting shader ? */
+ Batch_set_builtin_program(&batch, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3fv(&batch, "light", light_vec);
+ }
+ Batch_Uniform4fv(&batch, "color", fcolor);
+ Batch_draw(&batch);
- glCallList(displist);
+ gpuPopMatrix();
}
static void drawcube_size(float xsize, float ysize, float zsize)
{
static VertexFormat format = {0};
- static VertexBuffer vbo = {0};
+ static VertexBuffer vbo = {{0}};
static ElementListBuilder elb = {0};
static ElementList el = {0};
- static Batch batch = {0};
+ static Batch batch = {{0}};
if (format.attrib_ct == 0) {
/* Vertex format */
@@ -445,68 +450,87 @@ static void drawcube_size(float xsize, float ysize, float zsize)
Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- gpuMatrixBegin3D_legacy();
+ gpuPushMatrix();
gpuScale3f(xsize, ysize, zsize);
Batch_use_program(&batch);
Batch_Uniform4fv(&batch, "color", fcolor);
Batch_draw(&batch);
- gpuMatrixEnd();
+ gpuPopMatrix();
}
static void draw_bonevert(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- glPushMatrix();
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- glRotatef(90, 0, 1, 0);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- glRotatef(90, 1, 0, 0);
- gluDisk(qobj, 0.0, 0.05, 16, 1);
-
- gluDeleteQuadric(qobj);
-
- glPopMatrix();
- glEndList();
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {{0}};
+ static Batch batch = {{0}};
+
+ if (format.attrib_ct == 0) {
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 96);
+ for (int i = 0; i < 16; ++i) {
+ float vert[3] = {0.f, 0.f, 0.f};
+ const float r = 0.05f;
+
+ vert[0] = r * cosf(2 * M_PI * i / 16.f);
+ vert[1] = r * sinf(2 * M_PI * i / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 0, vert);
+ vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[1] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 1, vert);
+
+ vert[0] = 0.f;
+ vert[1] = r * cosf(2 * M_PI * i / 16.f);
+ vert[2] = r * sinf(2 * M_PI * i / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 2, vert);
+ vert[1] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 3, vert);
+
+ vert[1] = 0.f;
+ vert[0] = r * cosf(2 * M_PI * i / 16.f);
+ vert[2] = r * sinf(2 * M_PI * i / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 4, vert);
+ vert[0] = r * cosf(2 * M_PI * (i + 1) / 16.f);
+ vert[2] = r * sinf(2 * M_PI * (i + 1) / 16.f);
+ setAttrib(&vbo, pos, i * 6 + 5, vert);
+ }
+
+ Batch_init(&batch, GL_LINES, &vbo, NULL);
+ Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- glCallList(displist);
+ Batch_use_program(&batch);
+ Batch_Uniform4fv(&batch, "color", fcolor);
+ Batch_draw(&batch);
}
static void draw_bonevert_solid(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- /* Draw tips of a bone */
- gluSphere(qobj, 0.05, 8, 5);
- gluDeleteQuadric(qobj);
-
- glEndList();
+ Batch *batch = Batch_get_sphere(0);
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ gpuPushMatrix();
+ gpuScaleUniform(0.05);
+
+ if (flat_color) {
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ /* TODO replace with good default lighting shader ? */
+ Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3fv(batch, "light", light_vec);
}
+ Batch_Uniform4fv(batch, "color", fcolor);
+ Batch_draw(batch);
- glCallList(displist);
+ gpuPopMatrix();
}
static const float bone_octahedral_verts[6][3] = {
@@ -551,10 +575,10 @@ static const float bone_octahedral_solid_normals[8][3] = {
static void draw_bone_octahedral(void)
{
static VertexFormat format = {0};
- static VertexBuffer vbo = {0};
+ static VertexBuffer vbo = {{0}};
static ElementListBuilder elb = {0};
static ElementList el = {0};
- static Batch batch = {0};
+ static Batch batch = {{0}};
if (format.attrib_ct == 0) {
/* Vertex format */
@@ -578,52 +602,50 @@ static void draw_bone_octahedral(void)
Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
}
- gpuMatrixBegin3D_legacy();
-
Batch_use_program(&batch);
Batch_Uniform4fv(&batch, "color", fcolor);
Batch_draw(&batch);
-
- gpuMatrixEnd();
-}
+}
static void draw_bone_solid_octahedral(void)
{
- static GLuint displist = 0;
-
- if (displist == 0) {
- int i;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
-
-#if 1
- glBegin(GL_TRIANGLES);
- for (i = 0; i < 8; i++) {
- glNormal3fv(bone_octahedral_solid_normals[i]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
- glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
- }
-
- glEnd();
-
-#else /* not working because each vert needs a different normal */
- glEnableClientState(GL_NORMAL_ARRAY);
- glEnableClientState(GL_VERTEX_ARRAY);
- glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals);
- glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
- glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris) / sizeof(unsigned int),
- GL_UNSIGNED_INT, bone_octahedral_solid_tris);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
-#endif
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {{0}};
+ static Batch batch = {{0}};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ if (format.attrib_ct == 0) {
+ unsigned int v_idx = 0;
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int nor = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
- glEndList();
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 24);
+
+ for (int i = 0; i < 8; i++) {
+ add_solid_flat_triangle(&vbo, &v_idx, pos, nor,
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][0]],
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][1]],
+ bone_octahedral_verts[bone_octahedral_solid_tris[i][2]],
+ bone_octahedral_solid_normals[i]);
+ }
+
+ Batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
}
- glCallList(displist);
-}
+ if (flat_color) {
+ Batch_set_builtin_program(&batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ }
+ else {
+ /* TODO replace with good default lighting shader ? */
+ Batch_set_builtin_program(&batch, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3fv(&batch, "light", light_vec);
+ }
+ Batch_Uniform4fv(&batch, "color", fcolor);
+ Batch_draw(&batch);
+}
/* *************** Armature drawing, bones ******************* */
@@ -637,15 +659,20 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_ROOTSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
}
else {
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
if (dt > OB_WIRE)
@@ -660,24 +687,29 @@ static void draw_bone_points(const short dt, int armflag, unsigned int boneflag,
if (dt <= OB_WIRE) {
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
}
else {
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, 0);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
}
- glTranslatef(0.0f, 1.0f, 0.0f);
+ gpuPushMatrix();
+ gpuTranslate2f(0.0f, 1.0f);
if (dt > OB_WIRE)
draw_bonevert_solid();
else
draw_bonevert();
- glTranslatef(0.0f, -1.0f, 0.0f);
-
+ gpuPopMatrix();
}
/* 16 values of sin function (still same result!) */
@@ -776,8 +808,13 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
//mul_v3_fl(dirvec, head);
cross_v3_v3v3(norvec, dirvec, imat[2]);
-
- glBegin(GL_QUAD_STRIP);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immBegin(GL_TRIANGLE_STRIP, 66);
+ immUniformColor4ub(255, 255, 255, 50);
for (a = 0; a < 16; a++) {
vec[0] = -si[a] * dirvec[0] + co[a] * norvec[0];
@@ -787,10 +824,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, headvec, vec, head);
madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
- glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
}
for (a = 15; a >= 0; a--) {
@@ -801,10 +836,8 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, tailvec, vec, tail);
madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist);
- //glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
}
/* make it cyclic... */
@@ -815,12 +848,11 @@ static void draw_sphere_bone_dist(float smat[4][4], float imat[4][4], bPoseChann
madd_v3_v3v3fl(vec1, headvec, vec, head);
madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
- //glColor4ub(255, 255, 255, 50);
- glVertex3fv(vec1);
- //glColor4ub(255, 255, 255, 0);
- glVertex3fv(vec2);
+ immVertex3fv(pos, vec1);
+ immVertex3fv(pos, vec2);
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
@@ -832,6 +864,11 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
{
float head, tail /*, length*/;
float *headvec, *tailvec, dirvec[3];
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* figure out the sizes of spheres */
if (ebone) {
@@ -860,35 +897,49 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
/* sphere root color */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_ROOTSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
-
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
+
+ immUniformColor4fv(fcolor);
+
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
GPU_select_load_id(id | BONESEL_ROOT);
- drawcircball(GL_LINE_LOOP, headvec, head, imat);
+ imm_drawcircball(headvec, head, imat, pos);
}
/* Draw tip point */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) {
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_VERTEX, fcolor);
+ }
}
if (id != -1)
GPU_select_load_id(id | BONESEL_TIP);
- drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
+ imm_drawcircball(tailvec, tail, imat, pos);
/* base */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_WIRE_EDIT);
+ if (boneflag & BONE_SELECTED){
+ UI_GetThemeColor4fv(TH_SELECT, fcolor);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
+ }
}
sub_v3_v3v3(dirvec, tailvec, headvec);
@@ -914,34 +965,40 @@ static void draw_sphere_bone_wire(float smat[4][4], float imat[4][4],
if (id != -1)
GPU_select_load_id(id | BONESEL_BONE);
- glBegin(GL_LINES);
+ immBegin(GL_LINES, 4);
add_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
add_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
sub_v3_v3v3(vec, headvec, norvech);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
sub_v3_v3v3(vec, tailvec, norvect);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
- glEnd();
+ immEnd();
}
+
+ immUnbindProgram();
}
/* does wire only for outline selecting */
static void draw_sphere_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
- GLUquadricObj *qobj;
+ Batch *sphere = Batch_get_sphere(1);
float head, tail, length;
- float fac1, fac2;
-
- glPushMatrix();
- qobj = gluNewQuadric();
+ float fac1, fac2, size1, size2;
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
+
+ /* dt is always OB_SOlID */
+ Batch_set_builtin_program(sphere, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3fv(sphere, "light", light_vec);
+
+ gpuPushMatrix();
/* figure out the sizes of spheres */
if (ebone) {
@@ -962,110 +1019,124 @@ static void draw_sphere_bone(const short dt, int armflag, int boneflag, short co
}
/* move to z-axis space */
- glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
+ gpuRotateAxis(-90.0f, 'X');
- if (dt == OB_SOLID) {
- /* set up solid drawing */
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-
- gluQuadricDrawStyle(qobj, GLU_FILL);
- }
- else {
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
- }
-
/* sphere root color */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ if (boneflag & BONE_ROOTSEL)
+ UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
else if (dt == OB_SOLID)
- UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
if (id != -1)
GPU_select_load_id(id | BONESEL_ROOT);
- gluSphere(qobj, head, 16, 10);
+ gpuPushMatrix();
+ gpuScaleUniform(head);
+ Batch_Uniform4fv(sphere, "color", fcolor);
+ Batch_draw(sphere);
+ gpuPopMatrix();
}
/* Draw tip point */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColorShade(TH_BONE_SOLID, -30);
+ if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColorShade4fv(TH_BONE_SOLID, -30, fcolor);
}
if (id != -1)
GPU_select_load_id(id | BONESEL_TIP);
- glTranslatef(0.0f, 0.0f, length);
- gluSphere(qobj, tail, 16, 10);
- glTranslatef(0.0f, 0.0f, -length);
+ gpuTranslate3f(0.0f, 0.0f, length);
+
+ gpuPushMatrix();
+ gpuScaleUniform(tail);
+ Batch_use_program(sphere); /* hack to make the following uniforms stick */
+ Batch_Uniform4fv(sphere, "color", fcolor);
+ Batch_draw(sphere);
+ gpuPopMatrix();
+
+ gpuTranslate3f(0.0f, 0.0f, -length);
/* base */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
- else UI_ThemeColor(TH_BONE_SOLID);
+ if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
else if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
else if (dt == OB_SOLID)
- UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+
+ Batch_use_program(sphere); /* hack to make the following uniforms stick */
+ Batch_Uniform4fv(sphere, "color", fcolor);
fac1 = (length - head) / length;
fac2 = (length - tail) / length;
if (length > (head + tail)) {
+ size1 = fac2 * tail + (1.0f - fac2) * head;
+ size2 = fac1 * head + (1.0f - fac1) * tail;
+
if (id != -1)
GPU_select_load_id(id | BONESEL_BONE);
+ /* draw sphere on extrema */
+ gpuPushMatrix();
+ gpuTranslate3f(0.0f, 0.0f, length - tail);
+ gpuScaleUniform(size1);
+
+ Batch_draw(sphere);
+ gpuPopMatrix();
+
+ gpuPushMatrix();
+ gpuTranslate3f(0.0f, 0.0f, head);
+ gpuScaleUniform(size2);
+
+ Batch_draw(sphere);
+ gpuPopMatrix();
+
+ /* draw cynlinder between spheres */
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.0f, -1.0f);
-
- glTranslatef(0.0f, 0.0f, head);
- gluCylinder(qobj, fac1 * head + (1.0f - fac1) * tail, fac2 * tail + (1.0f - fac2) * head, length - head - tail, 16, 1);
- glTranslatef(0.0f, 0.0f, -head);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int nor = add_attrib(format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING);
+ immUniformColor4fv(fcolor);
+ immUniform3fv("light", light_vec);
+
+ gpuTranslate3f(0.0f, 0.0f, head);
+ imm_cylinder_nor(pos, nor, size2, size1, length - head - tail, 16, 1);
+
+ immUnbindProgram();
glDisable(GL_POLYGON_OFFSET_FILL);
-
- /* draw sphere on extrema */
- glTranslatef(0.0f, 0.0f, length - tail);
- gluSphere(qobj, fac2 * tail + (1.0f - fac2) * head, 16, 10);
- glTranslatef(0.0f, 0.0f, -length + tail);
-
- glTranslatef(0.0f, 0.0f, head);
- gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10);
}
else {
+ size1 = fac1 * head + (1.0f - fac1) * tail;
+
/* 1 sphere in center */
- glTranslatef(0.0f, 0.0f, (head + length - tail) / 2.0f);
- gluSphere(qobj, fac1 * head + (1.0f - fac1) * tail, 16, 10);
- }
-
- /* restore */
- if (dt == OB_SOLID) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ gpuTranslate3f(0.0f, 0.0f, (head + length - tail) / 2.0f);
+
+ gpuScaleUniform(size1);
+ Batch_draw(sphere);
}
- glPopMatrix();
- gluDeleteQuadric(qobj);
+ gpuPopMatrix();
}
-static GLubyte bm_dot6[] = {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0};
-static GLubyte bm_dot8[] = {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C};
-
-static GLubyte bm_dot5[] = {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0};
-static GLubyte bm_dot7[] = {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38};
-
-
static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id,
bPoseChannel *pchan, EditBone *ebone)
{
- /* call this once, avoid constant changing */
- BLI_assert(glaGetOneInt(GL_UNPACK_ALIGNMENT) == 1);
-
float length;
if (pchan)
@@ -1073,103 +1144,119 @@ static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned
else
length = ebone->length;
- glPushMatrix();
- glScalef(length, length, length);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ gpuPushMatrix();
+ gpuScaleUniform(length);
/* this chunk not in object mode */
if (armflag & (ARM_EDITMODE | ARM_POSEMODE)) {
glLineWidth(4.0f);
- if (G.f & G_PICKSEL) {
- /* no bitmap in selection mode, crashes 3d cards...
- * instead draw a solid point the same size */
- glPointSize(8.0f);
- }
+ glPointSize(8.0f);
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else if (armflag & ARM_EDITMODE) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
}
-
+
+ /* line */
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
+ if (id != -1)
+ GPU_select_load_id(id | BONESEL_BONE);
+
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
/* Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
- if (G.f & G_PICKSEL) {
+ if (G.f & G_PICKSEL)
GPU_select_load_id(id | BONESEL_ROOT);
- glBegin(GL_POINTS);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glEnd();
- }
- else {
- glRasterPos3f(0.0f, 0.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
- }
+
+ immBegin(GL_POINTS, 1);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
}
-
- if (id != -1)
- GPU_select_load_id((GLuint) id | BONESEL_BONE);
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
-
+
/* tip */
- if (G.f & G_PICKSEL) {
- /* no bitmap in selection mode, crashes 3d cards... */
+ if (G.f & G_PICKSEL)
GPU_select_load_id(id | BONESEL_TIP);
- glBegin(GL_POINTS);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
- }
- else {
- glRasterPos3f(0.0f, 1.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
- }
-
+
+ immBegin(GL_POINTS, 1);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+
/* further we send no names */
if (id != -1)
GPU_select_load_id(id & 0xFFFF); /* object tag, for bordersel optim */
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_LINEBONE, boneflag, constflag);
}
-
- glLineWidth(2.0);
-
+
+ /* Now draw the inner color */
+ glLineWidth(2.0f);
+ glPointSize(5.0f);
+
+ /* line */
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_SELECTED) UI_GetThemeColor4fv(TH_EDGE_SELECT, fcolor);
+ else UI_GetThemeColorShade4fv(TH_BACK, -30, fcolor);
+ }
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
+
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR);
+
/*Draw root point if we are not connected */
if ((boneflag & BONE_CONNECTED) == 0) {
- if ((G.f & G_PICKSEL) == 0) {
- /* no bitmap in selection mode, crashes 3d cards... */
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
- }
- glRasterPos3f(0.0f, 0.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
+ if (armflag & ARM_EDITMODE) {
+ if (boneflag & BONE_ROOTSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
}
+ immUniformColor4fv(fcolor);
+ immBegin(GL_POINTS, 1);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immEnd();
}
-
- if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
- else UI_ThemeColorShade(TH_BACK, -30);
- }
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, 1.0f, 0.0f);
- glEnd();
-
+
/* tip */
if ((G.f & G_PICKSEL) == 0) {
/* no bitmap in selection mode, crashes 3d cards... */
if (armflag & ARM_EDITMODE) {
- if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
- else UI_ThemeColor(TH_VERTEX);
+ if (boneflag & BONE_TIPSEL) UI_GetThemeColor4fv(TH_VERTEX_SELECT, fcolor);
+ else UI_GetThemeColor4fv(TH_VERTEX, fcolor);
}
- glRasterPos3f(0.0f, 1.0f, 0.0f);
- glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
+ immUniformColor4fv(fcolor);
+ immBegin(GL_POINTS, 1);
+ immVertex3f(pos, 0.0f, 1.0f, 0.0f);
+ immEnd();
}
-
- glPopMatrix();
+
+ immUnbindProgram();
+
+ gpuPopMatrix();
}
/* A partial copy of b_bone_spline_setup(), with just the parts for previewing editmode curve settings
@@ -1268,18 +1355,16 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, EditBone *ebo
}
for (a = 0; a < segments; a++) {
- glPushMatrix();
- glMultMatrixf(bbone[a].mat);
+ gpuPushMatrix();
+ gpuMultMatrix3D(bbone[a].mat);
if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
else drawcube_size(xwidth, dlen, zwidth);
- glPopMatrix();
+ gpuPopMatrix();
}
}
else {
- glPushMatrix();
if (dt == OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
else drawcube_size(xwidth, length, zwidth);
- glPopMatrix();
}
}
@@ -1302,26 +1387,27 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
/* draw points only if... */
if (armflag & ARM_EDITMODE) {
/* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
+ gpuPushMatrix();
+ gpuScaleUniform(length);
draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
+ gpuPopMatrix();
length *= 0.95f; /* make vertices visible */
}
/* colors for modes */
if (armflag & ARM_POSEMODE) {
if (dt <= OB_WIRE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
}
else if (armflag & ARM_EDITMODE) {
if (dt == OB_WIRE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
+ }
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
}
- else
- UI_ThemeColor(TH_BONE_SOLID);
}
if (id != -1) {
@@ -1330,33 +1416,31 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
/* set up solid drawing */
if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
-
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
- else
- UI_ThemeColor(TH_BONE_SOLID);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
+ else {
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ }
+ flat_color = false;
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
-
- /* disable solid drawing */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
else {
/* wire */
if (armflag & ARM_POSEMODE) {
- if (constflag) {
+ if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* set constraint colors */
- if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
+ if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
+ flat_color = true;
draw_b_bone_boxes(OB_SOLID, pchan, ebone, xwidth, length, zwidth);
glDisable(GL_BLEND);
}
/* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
}
@@ -1366,33 +1450,41 @@ static void draw_b_bone(const short dt, int armflag, int boneflag, short constfl
static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
{
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
if ((segments > 1) && (pchan)) {
float dlen = length / (float)segments;
Mat4 *bbone = bbones;
int a;
-
+
for (a = 0; a < segments; a++, bbone++) {
- glPushMatrix();
- glMultMatrixf(bbone->mat);
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, dlen, 0.0f);
- glEnd(); /* GL_LINES */
-
- glPopMatrix();
+ gpuPushMatrix();
+ gpuMultMatrix3D(bbone->mat);
+
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, dlen, 0.0f);
+ immEnd();
+
+ gpuPopMatrix();
}
}
else {
- glPushMatrix();
-
- glBegin(GL_LINES);
- glVertex3f(0.0f, 0.0f, 0.0f);
- glVertex3f(0.0f, length, 0.0f);
- glEnd();
-
- glPopMatrix();
+ gpuPushMatrix();
+
+ immBegin(GL_LINES, 2);
+ immVertex3f(pos, 0.0f, 0.0f, 0.0f);
+ immVertex3f(pos, 0.0f, length, 0.0f);
+ immEnd();
+
+ gpuPopMatrix();
}
+
+ immUnbindProgram();
}
static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id,
@@ -1418,10 +1510,11 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* draw points only if... */
if (armflag & ARM_EDITMODE) {
/* move to unitspace */
- glPushMatrix();
- glScalef(length, length, length);
+ gpuPushMatrix();
+ gpuScaleUniform(length);
+ flat_color = true;
draw_bone_points(dt, armflag, boneflag, id);
- glPopMatrix();
+ gpuPopMatrix();
length *= 0.95f; /* make vertices visible */
}
@@ -1439,10 +1532,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
/* colors for modes */
if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
else if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
}
/* draw normal */
@@ -1452,23 +1545,23 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons
static void draw_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, float length)
{
- /* Draw a 3d octahedral bone, we use normalized space based on length,
- * for display-lists */
-
- glScalef(length, length, length);
+ /* Draw a 3d octahedral bone, we use normalized space based on length */
+ gpuScaleUniform(length);
/* set up solid drawing */
if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- UI_ThemeColor(TH_BONE_SOLID);
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
+ flat_color = false;
}
+ else
+ flat_color = true;
/* colors for posemode */
if (armflag & ARM_POSEMODE) {
if (dt <= OB_WIRE)
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
else
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
}
@@ -1483,12 +1576,12 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
if (dt <= OB_WIRE) {
/* colors */
if (armflag & ARM_EDITMODE) {
- set_ebone_glColor(boneflag);
+ set_ebone_color(boneflag);
}
else if (armflag & ARM_POSEMODE) {
- if (constflag) {
+ if (constflag && ((G.f & G_PICKSEL) == 0)) {
/* draw constraint colors */
- if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
+ if (set_pchan_color(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
glEnable(GL_BLEND);
draw_bone_solid_octahedral();
@@ -1497,7 +1590,7 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
}
/* restore colors */
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, constflag);
}
}
draw_bone_octahedral();
@@ -1505,35 +1598,31 @@ static void draw_bone(const short dt, int armflag, int boneflag, short constflag
else {
/* solid */
if (armflag & ARM_POSEMODE)
- set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
+ set_pchan_color(PCHAN_COLOR_SOLID, boneflag, constflag);
else
- UI_ThemeColor(TH_BONE_SOLID);
- draw_bone_solid_octahedral();
- }
+ UI_GetThemeColor4fv(TH_BONE_SOLID, fcolor);
- /* disable solid drawing */
- if (dt > OB_WIRE) {
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ draw_bone_solid_octahedral();
}
}
-static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob,
+static void draw_custom_bone(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob,
const short dt, int armflag, int boneflag, unsigned int id, float length)
{
if (ob == NULL) return;
- glScalef(length, length, length);
+ gpuScaleUniform(length);
/* colors for posemode */
if (armflag & ARM_POSEMODE) {
- set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0);
+ set_pchan_color(PCHAN_COLOR_NORMAL, boneflag, 0);
}
if (id != -1) {
GPU_select_load_id((GLuint) id | BONESEL_BONE);
}
-
- draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
+
+ draw_object_instance(scene, sl, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE, fcolor);
}
@@ -1541,7 +1630,14 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
{
bConstraint *con;
bPoseChannel *parchan;
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(fcolor);
+
+ setlinestyle(3);
for (con = pchan->constraints.first; con; con = con->next) {
if (con->enforce == 0.0f)
continue;
@@ -1551,47 +1647,45 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
{
bKinematicConstraint *data = (bKinematicConstraint *)con->data;
int segcount = 0;
+ float ik_tip[3];
/* if only_temp, only draw if it is a temporary ik-chain */
if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
continue;
-
- setlinestyle(3);
- glBegin(GL_LINES);
-
+
/* exclude tip from chain? */
if ((data->flag & CONSTRAINT_IK_TIP) == 0)
parchan = pchan->parent;
else
parchan = pchan;
- glVertex3fv(parchan->pose_tail);
+ copy_v3_v3(ik_tip, parchan->pose_tail);
/* Find the chain's root */
while (parchan->parent) {
segcount++;
- if (segcount == data->rootbone || segcount > 255) {
- break; /* 255 is weak */
- }
+ /* FIXME: revise the breaking conditions */
+ if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */
parchan = parchan->parent;
}
- if (parchan)
- glVertex3fv(parchan->pose_head);
+
+ if (parchan) {
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, ik_tip);
+ immVertex3fv(pos, parchan->pose_head);
+ immEnd();
+ }
- glEnd();
- setlinestyle(0);
break;
}
case CONSTRAINT_TYPE_SPLINEIK:
{
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
int segcount = 0;
-
- setlinestyle(3);
- glBegin(GL_LINES);
+ float ik_tip[3];
parchan = pchan;
- glVertex3fv(parchan->pose_tail);
+ copy_v3_v3(ik_tip, parchan->pose_tail);
/* Find the chain's root */
while (parchan->parent) {
@@ -1601,18 +1695,21 @@ static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
parchan = parchan->parent;
}
/* Only draw line in case our chain is more than one bone long! */
- if (parchan != pchan) /* XXX revise the breaking conditions to only stop at the tail? */
- glVertex3fv(parchan->pose_head);
-
- glEnd();
- setlinestyle(0);
+ if (parchan != pchan) { /* XXX revise the breaking conditions to only stop at the tail? */
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, ik_tip);
+ immVertex3fv(pos, parchan->pose_head);
+ immEnd();
+ }
break;
}
}
}
+ setlinestyle(0);
+ immUnbindProgram();
}
-static void bgl_sphere_project(float ax, float az)
+static void imm_sphere_project(unsigned int pos, float ax, float az)
{
float dir[3], sine, q3;
@@ -1623,11 +1720,13 @@ static void bgl_sphere_project(float ax, float az)
dir[1] = 1.0f - 2.0f * sine;
dir[2] = ax * q3;
- glVertex3fv(dir);
+ immVertex3fv(pos, dir);
}
-static void draw_dof_ellipse(float ax, float az)
+static void draw_dof_ellipse(unsigned int pos, float ax, float az)
{
+ const int n = 16;
+ const int tri = n*n - 2*n + 1; /* Yay fancy math ! */
const float staticSine[16] = {
0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
@@ -1636,15 +1735,15 @@ static void draw_dof_ellipse(float ax, float az)
0.994521895368f, 1.0f
};
- int i, j, n = 16;
+ int i, j;
float x, z, px, pz;
glEnable(GL_BLEND);
glDepthMask(0);
- glColor4ub(70, 70, 70, 50);
+ immUniformColor4ub(70, 70, 70, 50);
- glBegin(GL_QUADS);
+ immBegin(GL_TRIANGLES, tri*3);
pz = 0.0f;
for (i = 1; i < n; i++) {
z = staticSine[i];
@@ -1654,36 +1753,35 @@ static void draw_dof_ellipse(float ax, float az)
x = staticSine[j];
if (j == n - i) {
- glEnd();
- glBegin(GL_TRIANGLES);
- bgl_sphere_project(ax * px, az * z);
- bgl_sphere_project(ax * px, az * pz);
- bgl_sphere_project(ax * x, az * pz);
- glEnd();
- glBegin(GL_QUADS);
+ imm_sphere_project(pos, ax * px, az * z);
+ imm_sphere_project(pos, ax * px, az * pz);
+ imm_sphere_project(pos, ax * x, az * pz);
}
else {
- bgl_sphere_project(ax * x, az * z);
- bgl_sphere_project(ax * x, az * pz);
- bgl_sphere_project(ax * px, az * pz);
- bgl_sphere_project(ax * px, az * z);
+ imm_sphere_project(pos, ax * x, az * z);
+ imm_sphere_project(pos, ax * x, az * pz);
+ imm_sphere_project(pos, ax * px, az * pz);
+
+ imm_sphere_project(pos, ax * px, az * pz);
+ imm_sphere_project(pos, ax * px, az * z);
+ imm_sphere_project(pos, ax * x, az * z);
}
px = x;
}
pz = z;
}
- glEnd();
+ immEnd();
glDisable(GL_BLEND);
glDepthMask(1);
- glColor3ub(0, 0, 0);
+ immUniformColor3ub(0, 0, 0);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, n);
for (i = 0; i < n; i++)
- bgl_sphere_project(staticSine[n - i - 1] * ax, staticSine[i] * az);
- glEnd();
+ imm_sphere_project(pos, staticSine[n - i - 1] * ax, staticSine[i] * az);
+ immEnd();
}
static void draw_pose_dofs(Object *ob)
@@ -1691,7 +1789,12 @@ static void draw_pose_dofs(Object *ob)
bArmature *arm = ob->data;
bPoseChannel *pchan;
Bone *bone;
-
+
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
bone = pchan->bone;
@@ -1705,54 +1808,55 @@ static void draw_pose_dofs(Object *ob)
int a, i;
/* in parent-bone pose, but own restspace */
- glPushMatrix();
+ gpuPushMatrix();
copy_v3_v3(posetrans, pchan->pose_mat[3]);
- glTranslate3fv(posetrans);
+ gpuTranslate3fv(posetrans);
if (pchan->parent) {
copy_m4_m4(mat, pchan->parent->pose_mat);
mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
- glMultMatrixf(mat);
+ gpuMultMatrix3D(mat);
}
copy_m4_m3(mat, pchan->bone->bone_mat);
- glMultMatrixf(mat);
+ gpuMultMatrix3D(mat);
scale = bone->length * pchan->size[1];
- glScalef(scale, scale, scale);
+ gpuScaleUniform(scale);
- if (pchan->ikflag & BONE_IK_XLIMIT) {
- if (pchan->ikflag & BONE_IK_ZLIMIT) {
- float amin[3], amax[3];
-
- for (i = 0; i < 3; i++) {
- /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
- amin[i] = sinf(pchan->limitmin[i] * 0.5f);
- amax[i] = sinf(pchan->limitmax[i] * 0.5f);
- }
-
- glScalef(1.0f, -1.0f, 1.0f);
- if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
- draw_dof_ellipse(amin[0], amin[2]);
- if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
- draw_dof_ellipse(amin[0], amax[2]);
- if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
- draw_dof_ellipse(amax[0], amin[2]);
- if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
- draw_dof_ellipse(amax[0], amax[2]);
- glScalef(1.0f, -1.0f, 1.0f);
+ if (((pchan->ikflag & BONE_IK_XLIMIT) != 0) &&
+ ((pchan->ikflag & BONE_IK_ZLIMIT) != 0))
+ {
+ float amin[3], amax[3];
+
+ for (i = 0; i < 3; i++) {
+ /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
+ amin[i] = sinf(pchan->limitmin[i] * 0.5f);
+ amax[i] = sinf(pchan->limitmax[i] * 0.5f);
}
+
+ gpuScale3f(1.0f, -1.0f, 1.0f);
+ if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(pos, amin[0], amin[2]);
+ if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(pos, amin[0], amax[2]);
+ if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
+ draw_dof_ellipse(pos, amax[0], amin[2]);
+ if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
+ draw_dof_ellipse(pos, amax[0], amax[2]);
+ gpuScale3f(1.0f, -1.0f, 1.0f); /* XXX same as above, is this intentional? */
}
/* arcs */
if (pchan->ikflag & BONE_IK_ZLIMIT) {
/* OpenGL requires rotations in degrees; so we're taking the average angle here */
theta = RAD2DEGF(0.5f * (pchan->limitmin[2] + pchan->limitmax[2]));
- glRotatef(theta, 0.0f, 0.0f, 1.0f);
+ gpuPushMatrix();
+ gpuRotateAxis(theta, 'Z');
- glColor3ub(50, 50, 255); /* blue, Z axis limit */
- glBegin(GL_LINE_STRIP);
+ immUniformColor3ub(50, 50, 255); /* blue, Z axis limit */
+ immBegin(GL_LINE_STRIP, 33);
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
@@ -1763,20 +1867,21 @@ static void draw_pose_dofs(Object *ob)
corner[i][0] = sinf(phi);
corner[i][1] = cosf(phi);
corner[i][2] = 0.0f;
- glVertex3fv(corner[i]);
+ immVertex3fv(pos, corner[i]);
}
- glEnd();
+ immEnd();
- glRotatef(-theta, 0.0f, 0.0f, 1.0f);
+ gpuPopMatrix();
}
if (pchan->ikflag & BONE_IK_XLIMIT) {
/* OpenGL requires rotations in degrees; so we're taking the average angle here */
theta = RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
- glRotatef(theta, 1.0f, 0.0f, 0.0f);
+ gpuPushMatrix();
+ gpuRotateAxis(theta, 'X');
- glColor3ub(255, 50, 50); /* Red, X axis limit */
- glBegin(GL_LINE_STRIP);
+ immUniformColor3ub(255, 50, 50); /* Red, X axis limit */
+ immBegin(GL_LINE_STRIP, 33);
for (a = -16; a <= 16; a++) {
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
float fac = ((float)a) / 16.0f * 0.5f;
@@ -1786,21 +1891,23 @@ static void draw_pose_dofs(Object *ob)
corner[i][0] = 0.0f;
corner[i][1] = sinf(phi);
corner[i][2] = cosf(phi);
- glVertex3fv(corner[i]);
+ immVertex3fv(pos, corner[i]);
}
- glEnd();
+ immEnd();
- glRotatef(-theta, 1.0f, 0.0f, 0.0f);
+ gpuPopMatrix();
}
/* out of cone, out of bone */
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
}
}
}
+
+ immUnbindProgram();
}
static void bone_matrix_translate_y(float mat[4][4], float y)
@@ -1813,7 +1920,7 @@ static void bone_matrix_translate_y(float mat[4][4], float y)
}
/* assumes object is Armature with pose */
-static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base,
+static void draw_pose_bones(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
const short dt, const unsigned char ob_wire_col[4],
const bool do_const_color, const bool is_outline)
{
@@ -1833,14 +1940,12 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
bool draw_wire = false;
int flag;
bool is_cull_enabled;
-
- /* TODO find a way to overcome this.
- * used in case do_const_color is true */
- glGetFloatv(GL_CURRENT_COLOR, fcolor);
/* being set below */
arm->layer_used = 0;
-
+
+ rgba_uchar_to_float(fcolor, ob_wire_col);
+
/* precalc inverse matrix for drawing screen aligned */
if (arm->drawtype == ARM_ENVELOPE) {
/* precalc inverse matrix for drawing screen aligned */
@@ -1901,13 +2006,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
{
if (bone->layer & arm->layer) {
const bool use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
- glPushMatrix();
+ gpuPushMatrix();
if (use_custom && pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
+ gpuMultMatrix3D(pchan->custom_tx->pose_mat);
}
else {
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix3D(pchan->pose_mat);
}
/* catch exception for bone with hidden parent */
@@ -1942,7 +2047,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
glDisable(GL_CULL_FACE);
}
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
+ draw_custom_bone(scene, sl, v3d, rv3d, pchan->custom,
OB_SOLID, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
}
}
@@ -1969,7 +2074,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
}
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -2005,13 +2110,13 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
if (bone->layer & arm->layer) {
if (pchan->custom) {
if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
- glPushMatrix();
+ gpuPushMatrix();
if (pchan->custom_tx) {
- glMultMatrixf(pchan->custom_tx->pose_mat);
+ gpuMultMatrix3D(pchan->custom_tx->pose_mat);
}
else {
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix3D(pchan->pose_mat);
}
/* prepare colors */
@@ -2021,7 +2126,6 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
else if (arm->flag & ARM_POSEMODE)
set_pchan_colorset(ob, pchan);
else {
- glColor3ubv(ob_wire_col);
rgba_uchar_to_float(fcolor, ob_wire_col);
}
@@ -2034,10 +2138,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
if (bone == arm->act_bone)
flag |= BONE_DRAW_ACTIVE;
- draw_custom_bone(scene, v3d, rv3d, pchan->custom,
+ draw_custom_bone(scene, sl, v3d, rv3d, pchan->custom,
OB_WIRE, arm->flag, flag, index, PCHAN_CUSTOM_DRAW_SIZE(pchan));
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -2096,16 +2200,25 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
* - only if V3D_HIDE_HELPLINES is enabled...
*/
if ((do_dashed & DASH_HELP_LINES) && ((bone->flag & BONE_CONNECTED) == 0)) {
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
if (arm->flag & ARM_POSEMODE) {
GPU_select_load_id(index & 0xFFFF); /* object tag, for bordersel optim */
- UI_ThemeColor(TH_WIRE);
+ UI_GetThemeColor4fv(TH_WIRE, fcolor);
+ immUniformColor4fv(fcolor);
}
+
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(pchan->pose_head);
- glVertex3fv(pchan->parent->pose_tail);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, pchan->pose_head);
+ immVertex3fv(pos, pchan->parent->pose_tail);
+ immEnd();
setlinestyle(0);
+
+ immUnbindProgram();
}
/* Draw a line to IK root bone
@@ -2114,8 +2227,8 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
if (arm->flag & ARM_POSEMODE) {
if (constflag & PCHAN_HAS_IK) {
if (bone->flag & BONE_SELECTED) {
- if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
- else glColor3ub(200, 200, 50); /* add theme! */
+ if (constflag & PCHAN_HAS_TARGET) rgba_float_args_set(fcolor, 200.f/255.f, 120.f/255.f, 0.f/255.f, 1.0f);
+ else rgba_float_args_set(fcolor, 200.f/255.f, 200.f/255.f, 50.f/255.f, 1.0f); /* add theme! */
GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
@@ -2123,7 +2236,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
}
else if (constflag & PCHAN_HAS_SPLINEIK) {
if (bone->flag & BONE_SELECTED) {
- glColor3ub(150, 200, 50); /* add theme! */
+ rgba_float_args_set(fcolor, 150.f/255.f, 200.f/255.f, 50.f/255.f, 1.0f); /* add theme! */
GPU_select_load_id(index & 0xFFFF);
pchan_draw_IK_root_lines(pchan, !(do_dashed & DASH_HELP_LINES));
@@ -2132,9 +2245,9 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
}
}
- glPushMatrix();
+ gpuPushMatrix();
if (arm->drawtype != ARM_ENVELOPE)
- glMultMatrixf(pchan->pose_mat);
+ gpuMultMatrix3D(pchan->pose_mat);
/* catch exception for bone with hidden parent */
flag = bone->flag;
@@ -2171,7 +2284,7 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
else
draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -2206,19 +2319,10 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
float vec[3];
unsigned char col[4];
- if (do_const_color) {
- /* so we can draw bone names in current const color */
- float tcol[4];
- glGetFloatv(GL_CURRENT_COLOR, tcol);
- rgb_float_to_uchar(col, tcol);
- col[3] = 255;
- }
- else {
- col[0] = ob_wire_col[0];
- col[1] = ob_wire_col[1];
- col[2] = ob_wire_col[2];
- col[3] = 255;
- }
+ col[0] = ob_wire_col[0];
+ col[1] = ob_wire_col[1];
+ col[2] = ob_wire_col[2];
+ col[3] = 255;
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -2241,16 +2345,16 @@ static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *
/* Draw additional axes on the bone tail */
if ((arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE)) {
- glPushMatrix();
+ gpuPushMatrix();
copy_m4_m4(bmat, pchan->pose_mat);
bone_matrix_translate_y(bmat, pchan->bone->length);
- glMultMatrixf(bmat);
+ gpuMultMatrix3D(bmat);
float viewmat_pchan[4][4];
mul_m4_m4m4(viewmat_pchan, rv3d->viewmatob, bmat);
drawaxes(viewmat_pchan, pchan->bone->length * 0.25f, OB_ARROWS, col);
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -2316,9 +2420,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
for (eBone = arm->edbo->first, index = 0; eBone; eBone = eBone->next, index++) {
if (eBone->layer & arm->layer) {
if ((eBone->flag & BONE_HIDDEN_A) == 0) {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
+ gpuMultMatrix3D(bmat);
/* catch exception for bone with hidden parent */
flag = eBone->flag;
@@ -2340,7 +2444,7 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
}
- glPopMatrix();
+ gpuPopMatrix();
}
}
}
@@ -2378,9 +2482,9 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
}
else {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
- glMultMatrixf(bmat);
+ gpuMultMatrix3D(bmat);
if (arm->drawtype == ARM_LINE)
draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
@@ -2391,21 +2495,28 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
else
draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
- glPopMatrix();
+ gpuPopMatrix();
}
/* offset to parent */
if (eBone->parent) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
GPU_select_load_id(-1); /* -1 here is OK! */
- setlinestyle(3);
-
- glBegin(GL_LINES);
- glVertex3fv(eBone->parent->tail);
- glVertex3fv(eBone->head);
- glEnd();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, fcolor);
+ immUniformColor4fv(fcolor);
+ setlinestyle(3);
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, eBone->head);
+ immVertex3fv(pos, eBone->parent->tail);
+ immEnd();
setlinestyle(0);
+
+ immUnbindProgram();
}
}
}
@@ -2443,21 +2554,20 @@ static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, const short dt)
/* Draw name */
if (arm->flag & ARM_DRAWNAMES) {
mid_v3_v3v3(vec, eBone->head, eBone->tail);
- glRasterPos3fv(vec);
view3d_cached_text_draw_add(vec, eBone->name, strlen(eBone->name), 10, 0, col);
}
/* Draw additional axes */
if (arm->flag & ARM_DRAWAXES) {
- glPushMatrix();
+ gpuPushMatrix();
get_matrix_editbone(eBone, bmat);
bone_matrix_translate_y(bmat, eBone->length);
- glMultMatrixf(bmat);
+ gpuMultMatrix3D(bmat);
float viewmat_ebone[4][4];
mul_m4_m4m4(viewmat_ebone, rv3d->viewmatob, bmat);
drawaxes(viewmat_ebone, eBone->length * 0.25f, OB_ARROWS, col);
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -2530,7 +2640,7 @@ static void ghost_poses_tag_unselected(Object *ob, short unset)
/* draw ghosts that occur within a frame range
* note: object should be in posemode
*/
-static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
+static void draw_ghost_poses_range(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2538,6 +2648,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseL
bPose *posen, *poseo;
float start, end, stepsize, range, colfac;
int cfrao, flago;
+ unsigned char col[4];
start = (float)arm->ghostsf;
end = (float)arm->ghostef;
@@ -2570,11 +2681,11 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseL
/* draw from first frame of range to last */
for (CFRA = (int)start; CFRA <= end; CFRA += (int)stepsize) {
colfac = (end - (float)CFRA) / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ draw_pose_bones(scene, sl, v3d, ar, base, OB_WIRE, col, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2596,7 +2707,7 @@ static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, BaseL
/* draw ghosts on keyframes in action within range
* - object should be in posemode
*/
-static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
+static void draw_ghost_poses_keys(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, BaseLegacy *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2607,6 +2718,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLe
ActKeyColumn *ak, *akn;
float start, end, range, colfac, i;
int cfrao, flago;
+ unsigned char col[4];
start = (float)arm->ghostsf;
end = (float)arm->ghostef;
@@ -2648,13 +2760,13 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLe
/* draw from first frame of range to last */
for (ak = keys.first, i = 0; ak; ak = ak->next, i++) {
colfac = i / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
CFRA = (int)ak->cfra;
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ draw_pose_bones(scene, sl, v3d, ar, base, OB_WIRE, col, true, false);
}
glDisable(GL_BLEND);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
@@ -2677,7 +2789,7 @@ static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, BaseLe
/* draw ghosts around current frame
* - object is supposed to be armature in posemode
*/
-static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy *base)
+static void draw_ghost_poses(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base)
{
Object *ob = base->object;
AnimData *adt = BKE_animdata_from_id(&ob->id);
@@ -2685,6 +2797,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy
bPose *posen, *poseo;
float cur, start, end, stepsize, range, colfac, actframe, ctime;
int cfrao, flago;
+ unsigned char col[4];
/* pre conditions, get an action with sufficient frames */
if (ELEM(NULL, adt, adt->action))
@@ -2722,7 +2835,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy
for (cur = stepsize; cur < range; cur += stepsize) {
ctime = cur - (float)fmod(cfrao, stepsize); /* ensures consistent stepping */
colfac = ctime / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
/* only within action range */
if (actframe + ctime >= start && actframe + ctime <= end) {
@@ -2731,13 +2844,13 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ draw_pose_bones(scene, sl, v3d, ar, base, OB_WIRE, col, true, false);
}
}
ctime = cur + (float)fmod((float)cfrao, stepsize) - stepsize + 1.0f; /* ensures consistent stepping */
colfac = ctime / range;
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)));
+ UI_GetThemeColorShadeAlpha4ubv(TH_WIRE, 0, -128 - (int)(120.0f * sqrtf(colfac)), col);
/* only within action range */
if ((actframe - ctime >= start) && (actframe - ctime <= end)) {
@@ -2746,7 +2859,7 @@ static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, BaseLegacy
if (CFRA != cfrao) {
BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
BKE_pose_where_is(scene, ob);
- draw_pose_bones(scene, v3d, ar, base, OB_WIRE, NULL, true, false);
+ draw_pose_bones(scene, sl, v3d, ar, base, OB_WIRE, col, true, false);
}
}
}
@@ -2782,11 +2895,7 @@ bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base
if (v3d->flag2 & V3D_RENDER_OVERRIDE)
return true;
- /* needed for 'draw_line_bone' which draws pixel. */
- if (arm->drawtype == ARM_LINE) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- }
-
+#if 0 /* Not used until lighting is properly reimplemented */
if (dt > OB_WIRE) {
/* we use color for solid lighting */
if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
@@ -2801,7 +2910,8 @@ bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW); /* only for lighting... */
}
}
-
+#endif
+
/* arm->flag is being used to detect mode... */
/* editmode? */
if (arm->edbo) {
@@ -2834,14 +2944,14 @@ bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base
}
else if (ob->mode & OB_MODE_POSE) {
if (arm->ghosttype == ARM_GHOST_RANGE) {
- draw_ghost_poses_range(scene, v3d, ar, base);
+ draw_ghost_poses_range(scene, sl, v3d, ar, base);
}
else if (arm->ghosttype == ARM_GHOST_KEYS) {
- draw_ghost_poses_keys(scene, v3d, ar, base);
+ draw_ghost_poses_keys(scene, sl, v3d, ar, base);
}
else if (arm->ghosttype == ARM_GHOST_CUR) {
if (arm->ghostep)
- draw_ghost_poses(scene, v3d, ar, base);
+ draw_ghost_poses(scene, sl, v3d, ar, base);
}
if ((dflag & DRAW_SCENESET) == 0) {
if (ob == OBACT_NEW)
@@ -2854,11 +2964,8 @@ bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base
}
}
}
- draw_pose_bones(scene, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline);
+ draw_pose_bones(scene, sl, v3d, ar, base, dt, ob_wire_col, (dflag & DRAW_CONSTCOLOR), is_outline);
arm->flag &= ~ARM_POSEMODE;
-
- if (ob->mode & OB_MODE_POSE)
- UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
}
else {
retval = true;
@@ -2867,9 +2974,5 @@ bool draw_armature(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base
/* restore */
glFrontFace(GL_CCW);
- if (arm->drawtype == ARM_LINE) {
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
- }
-
return retval;
}
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index ecbfd5c7c85..92fb8d3efa1 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -55,7 +55,6 @@
#include "BKE_editmesh.h"
#include "BKE_scene.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "UI_resources.h"
@@ -64,6 +63,7 @@
#include "GPU_material.h"
#include "GPU_basic_shader.h"
#include "GPU_shader.h"
+#include "GPU_matrix.h"
#include "RE_engine.h"
@@ -547,10 +547,10 @@ static void draw_textured_end(void)
* of and restored the light settings it changed.
* - zr
*/
- glPushMatrix();
- glLoadIdentity();
+ gpuPushMatrix();
+ gpuLoadIdentity();
GPU_default_lights();
- glPopMatrix();
+ gpuPopMatrix();
}
static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool has_mcol, int matnr)
@@ -777,7 +777,7 @@ static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int ind
return DM_DRAW_OPTION_NORMAL;
}
-static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
+static void draw_mesh_text(Scene *scene, SceneLayer *sl, Object *ob, int glsl)
{
Mesh *me = ob->data;
DerivedMesh *ddm;
@@ -803,7 +803,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
/* don't draw when editing */
if (ob->mode & OB_MODE_EDIT)
return;
- else if (ob == OBACT)
+ else if (ob == OBACT_NEW)
if (BKE_paint_select_elem_test(ob))
return;
@@ -947,7 +947,7 @@ static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
return 1;
}
-static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+static void draw_mesh_textured_old(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d,
Object *ob, DerivedMesh *dm, const int draw_flags)
{
Mesh *me = ob->data;
@@ -984,7 +984,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
dm_draw_flag = DM_DRAW_USE_ACTIVE_UV;
}
- if (ob == OBACT) {
+ if (ob == OBACT_NEW) {
if (ob->mode & OB_MODE_WEIGHT_PAINT) {
dm_draw_flag |= DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH | DM_DRAW_SKIP_HIDDEN;
}
@@ -1040,7 +1040,7 @@ static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d
/* draw game engine text hack */
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
if (BKE_bproperty_object_get(ob, "Text")) {
- draw_mesh_text(scene, ob, 0);
+ draw_mesh_text(scene, sl, ob, 0);
}
}
@@ -1104,7 +1104,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
glBindTexture(GL_TEXTURE_2D, ima->bindcode[TEXTARGET_TEXTURE_2D]);
glMatrixMode(GL_TEXTURE);
- glLoadMatrixf(texbase->tex_mapping.mat);
+ glLoadMatrixf((float*) texbase->tex_mapping.mat); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
/* use active UV texture layer */
@@ -1140,7 +1140,7 @@ static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
}
else {
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
/* enable solid material */
@@ -1174,7 +1174,7 @@ static bool tex_mat_set_face_editmesh_cb(void *userData, int index)
return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
}
-void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+void draw_mesh_textured(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d,
Object *ob, DerivedMesh *dm, const int draw_flags)
{
/* if not cycles, or preview-modifiers, or drawing matcaps */
@@ -1183,7 +1183,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
(BKE_scene_use_new_shading_nodes(scene) == false) ||
((ob->mode & OB_MODE_TEXTURE_PAINT) && ELEM(v3d->drawtype, OB_TEXTURE, OB_SOLID)))
{
- draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
+ draw_mesh_textured_old(scene, sl, v3d, rv3d, ob, dm, draw_flags);
return;
}
else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
@@ -1217,7 +1217,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
const int drawtype = view3d_effective_drawtype(v3d);
bool glsl = (drawtype == OB_MATERIAL) && !picking;
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
if (glsl || picking) {
/* draw glsl or solid */
@@ -1243,7 +1243,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glFrontFace(GL_CCW);
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
/* faceselect mode drawing over textured mesh */
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 5d821734b63..782bd20f05f 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -136,6 +136,7 @@ typedef struct drawDMVerts_userData {
BMVert *eve_act;
char sel;
+ unsigned int pos, color;
/* cached theme values */
unsigned char th_editmesh_active[4];
@@ -188,6 +189,7 @@ typedef struct drawDMFacesSel_userData {
} drawDMFacesSel_userData;
typedef struct drawDMNormal_userData {
+ unsigned int pos;
BMesh *bm;
int uniform_scale;
float normalsize;
@@ -196,6 +198,7 @@ typedef struct drawDMNormal_userData {
} drawDMNormal_userData;
typedef struct drawMVertOffset_userData {
+ unsigned int pos, col;
MVert *mvert;
int offset;
} drawMVertOffset_userData;
@@ -203,9 +206,11 @@ typedef struct drawMVertOffset_userData {
typedef struct drawDMLayer_userData {
BMesh *bm;
int cd_layer_offset;
+ unsigned int pos, col;
} drawDMLayer_userData;
typedef struct drawBMOffset_userData {
+ unsigned int pos, col;
BMesh *bm;
int offset;
} drawBMOffset_userData;
@@ -213,6 +218,7 @@ typedef struct drawBMOffset_userData {
typedef struct drawBMSelect_userData {
BMesh *bm;
bool select;
+ unsigned int pos;
} drawBMSelect_userData;
@@ -221,17 +227,14 @@ static void drawcircle_size(float size, unsigned pos);
static void draw_empty_sphere(float size, unsigned pos);
static void draw_empty_cone(float size, unsigned pos);
-static void draw_box(const float vec[8][3], bool solid);
-
-static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac)
+static void ob_wire_color_blend_theme_id(const unsigned char ob_wire_col[4], const int theme_id, float fac, float r_col[3])
{
- float col_wire[3], col_bg[3], col[3];
+ float col_wire[3], col_bg[3];
rgb_uchar_to_float(col_wire, ob_wire_col);
UI_GetThemeColor3fv(theme_id, col_bg);
- interp_v3_v3v3(col, col_bg, col_wire, fac);
- glColor3fv(col);
+ interp_v3_v3v3(r_col, col_bg, col_wire, fac);
}
int view3d_effective_drawtype(const struct View3D *v3d)
@@ -303,13 +306,13 @@ static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
/* check for glsl drawing */
-bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
+bool draw_glsl_material(Scene *scene, SceneLayer *sl, Object *ob, View3D *v3d, const char dt)
{
if (G.f & G_PICKSEL)
return false;
if (!check_object_draw_texture(scene, v3d, dt))
return false;
- if (ob == OBACT && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
+ if (ob == OBACT_NEW && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))
return false;
if (v3d->flag2 & V3D_SHOW_SOLID_MATCAP)
@@ -323,7 +326,7 @@ bool draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, const char dt)
return false;
}
-static bool check_alpha_pass(BaseLegacy *base)
+static bool check_alpha_pass(Base *base)
{
if (base->flag_legacy & OB_FROMDUPLI)
return false;
@@ -775,18 +778,6 @@ static void circball_array_fill(float verts[CIRCLE_RESOL][3], const float cent[3
}
}
-void drawcircball(int mode, const float cent[3], float rad, const float tmat[4][4])
-{
- float verts[CIRCLE_RESOL][3];
-
- circball_array_fill(verts, cent, rad, tmat);
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, verts);
- glDrawArrays(mode, 0, CIRCLE_RESOL);
- glDisableClientState(GL_VERTEX_ARRAY);
-}
-
void imm_drawcircball(const float cent[3], float rad, const float tmat[4][4], unsigned pos)
{
float verts[CIRCLE_RESOL][3];
@@ -815,7 +806,7 @@ static void drawcentercircle(View3D *v3d, RegionView3D *UNUSED(rv3d), const floa
GPU_enable_program_point_size();
unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform1f("size", size);
if (special_color) {
@@ -939,24 +930,16 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
if (tot) {
int col_pack_prev = 0;
-#if 0
- bglMats mats; /* ZBuffer depth vars */
- double ux, uy, uz;
- float depth;
-
- if (v3d->zbuf)
- bgl_get_mats(&mats);
-#endif
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_disable();
}
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ float original_proj[4][4];
+ gpuGetProjectionMatrix3D(original_proj);
wmOrtho2_region_pixelspace(ar);
- glLoadIdentity();
+
+ gpuPushMatrix();
+ gpuLoadIdentity();
if (depth_write) {
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
@@ -968,7 +951,7 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
for (vos = g_v3d_strings[g_v3d_string_level]; vos; vos = vos->next) {
if (vos->sco[0] != IS_CLIPPED) {
if (col_pack_prev != vos->col.pack) {
- glColor3ubv(vos->col.ub);
+ //glColor3ubv(vos->col.ub);
col_pack_prev = vos->col.pack;
}
@@ -990,10 +973,8 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write, flo
glDepthMask(GL_TRUE);
}
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix();
+ gpuLoadProjectionMatrix3D(original_proj); /* TODO: make this more 2D friendly */
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_enable();
@@ -1272,7 +1253,6 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
}
/* we first draw only the screen aligned & fixed scale stuff */
- gpuMatrixBegin3D_legacy();
gpuPushMatrix();
gpuLoadMatrix3D(rv3d->viewmat);
@@ -1323,7 +1303,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
immUniform1f("size", lampdot_size);
immUniform1f("outlineWidth", outlineWidth);
immUniformColor3fvAlpha(color, 0.3f);
@@ -1376,7 +1356,9 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
}
else {
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
- immUniformColor4fv(curcol);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ immUniformColor4fv(curcol);
+ }
circrad = 0.0f;
}
@@ -1625,7 +1607,7 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
glDisable(GL_BLEND);
immUnbindProgram();
- gpuMatrixEnd();
+ gpuPopMatrix();
}
static void draw_limit_line(float sta, float end, const short dflag, const unsigned char col[3], unsigned pos)
@@ -1669,26 +1651,6 @@ bool view3d_camera_border_hack_test = false;
/* ****************** draw clip data *************** */
-static void draw_bundle_sphere(void)
-{
- static GLuint displist = 0;
-
- if (displist == 0) {
- GLUquadricObj *qobj;
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
- qobj = gluNewQuadric();
- gluQuadricDrawStyle(qobj, GLU_FILL);
- gluSphere(qobj, 0.05, 8, 8);
- gluDeleteQuadric(qobj);
-
- glEndList();
- }
-
- glCallList(displist);
-}
-
static void draw_viewport_object_reconstruction(
Scene *scene, BaseLegacy *base, const View3D *v3d, const RegionView3D *rv3d,
MovieClip *clip, MovieTrackingObject *tracking_object,
@@ -1714,7 +1676,7 @@ static void draw_viewport_object_reconstruction(
if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0)
mul_v3_fl(camera_size, tracking_object->scale);
- glPushMatrix();
+ gpuPushMatrix();
if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
/* current ogl matrix is translated in camera space, bundles should
@@ -1722,8 +1684,8 @@ static void draw_viewport_object_reconstruction(
* from current ogl matrix */
invert_m4_m4(imat, base->object->obmat);
- glMultMatrixf(imat);
- glMultMatrixf(mat);
+ gpuMultMatrix3D(imat);
+ gpuMultMatrix3D(mat);
}
else {
float obmat[4][4];
@@ -1732,7 +1694,7 @@ static void draw_viewport_object_reconstruction(
BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, framenr, obmat);
invert_m4_m4(imat, obmat);
- glMultMatrixf(imat);
+ gpuMultMatrix3D(imat);
}
for (track = tracksbase->first; track; track = track->next) {
@@ -1747,11 +1709,11 @@ static void draw_viewport_object_reconstruction(
if (dflag & DRAW_PICKING)
GPU_select_load_id(base->selcol + (tracknr << 16));
- glPushMatrix();
- glTranslate3fv(track->bundle_pos);
- glScalef(v3d->bundle_size / 0.05f / camera_size[0],
- v3d->bundle_size / 0.05f / camera_size[1],
- v3d->bundle_size / 0.05f / camera_size[2]);
+ gpuPushMatrix();
+ gpuTranslate3fv(track->bundle_pos);
+ gpuScale3f(v3d->bundle_size / 0.05f / camera_size[0],
+ v3d->bundle_size / 0.05f / camera_size[1],
+ v3d->bundle_size / 0.05f / camera_size[2]);
const int v3d_drawtype = view3d_effective_drawtype(v3d);
if (v3d_drawtype == OB_WIRE) {
@@ -1771,26 +1733,46 @@ static void draw_viewport_object_reconstruction(
}
else if (v3d_drawtype > OB_WIRE) {
if (v3d->bundle_drawtype == OB_EMPTY_SPHERE) {
+ Batch *batch;
+
+ gpuScaleUniform(0.05f);
+
/* selection outline */
if (selected) {
+ batch = Batch_get_sphere_wire(1);
+
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ Batch_Uniform4f(batch, "color",
+ ob_wire_col[0]/255.f,
+ ob_wire_col[1]/255.f,
+ ob_wire_col[2]/255.f, 1.0f);
+ }
+ else {
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_DEPTH_ONLY);
}
-
glLineWidth(2.0f);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- draw_bundle_sphere();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ Batch_draw(batch);
}
+ batch = Batch_get_sphere(0);
+
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (track->flag & TRACK_CUSTOMCOLOR) glColor3fv(track->color);
- else UI_ThemeColor(TH_BUNDLE_SOLID);
+ const float light[3] = {0.0f, 0.0f, 1.0f};
+ float col[3];
+ Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3fv(batch, "light", light);
+
+ if (track->flag & TRACK_CUSTOMCOLOR) copy_v3_v3(col, track->color);
+ else UI_GetThemeColor3fv(TH_BUNDLE_SOLID, col);
+ Batch_Uniform4f(batch, "color", col[0], col[1], col[2], 1.0f);
+ }
+ else {
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_DEPTH_ONLY);
}
- draw_bundle_sphere();
+ Batch_draw(batch);
}
else {
unsigned char color[4];
@@ -1811,7 +1793,7 @@ static void draw_viewport_object_reconstruction(
}
}
- glPopMatrix();
+ gpuPopMatrix();
if ((dflag & DRAW_PICKING) == 0 && (v3d->flag2 & V3D_SHOW_BUNDLENAME)) {
float pos[3];
@@ -1831,22 +1813,27 @@ static void draw_viewport_object_reconstruction(
MovieTrackingReconstruction *reconstruction;
reconstruction = BKE_tracking_object_get_reconstruction(tracking, tracking_object);
- if (reconstruction->camnr) {
+ if (reconstruction->camnr >= 2) {
MovieReconstructedCamera *camera = reconstruction->cameras;
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_CAMERA_PATH);
- UI_ThemeColor(TH_CAMERA_PATH);
glLineWidth(2.0f);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, reconstruction->camnr);
for (int a = 0; a < reconstruction->camnr; a++, camera++) {
- glVertex3fv(camera->mat[3]);
+ immVertex3fv(pos, camera->mat[3]);
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
}
}
- glPopMatrix();
+ gpuPopMatrix();
*global_track_index = tracknr;
}
@@ -1881,10 +1868,6 @@ static void draw_viewport_reconstruction(
/* restore */
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(ob_wire_col);
- }
-
if (dflag & DRAW_PICKING)
GPU_select_load_id(base->selcol);
}
@@ -2185,8 +2168,6 @@ void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
BKE_camera_view_frame_ex(scene, cam, cam->drawsize, is_view, scale,
asp, shift, &drawsize, vec);
- gpuMatrixBegin3D_legacy();
-
unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (ob_wire_col) {
@@ -2216,7 +2197,6 @@ void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
if (is_view) {
immUnbindProgram();
- gpuMatrixEnd();
return;
}
@@ -2291,7 +2271,6 @@ void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
}
immUnbindProgram();
- gpuMatrixEnd();
}
/* flag similar to draw_object() */
@@ -2341,16 +2320,18 @@ void drawspeaker(const unsigned char ob_wire_col[3])
immUnbindProgram();
}
-static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel)
+static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short sel,
+ unsigned int pos, unsigned int color)
{
BPoint *bp = lt->def;
const float *co = dl ? dl->verts : NULL;
+ float active_color[4], draw_color[4];
- const int color = sel ? TH_VERTEX_SELECT : TH_VERTEX;
- UI_ThemeColor(color);
+ UI_GetThemeColor4fv(sel ? TH_VERTEX_SELECT : TH_VERTEX, draw_color);
+ UI_GetThemeColor4fv(TH_ACTIVE_VERT, active_color);
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+ immBeginAtMost(GL_POINTS, lt->pntsw * lt->pntsv * lt->pntsu);
for (int w = 0; w < lt->pntsw; w++) {
int wxt = (w == 0 || w == lt->pntsw - 1);
@@ -2362,12 +2343,12 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
if (bp->hide == 0) {
/* check for active BPoint and ensure selected */
if ((bp == actbp) && (bp->f1 & SELECT)) {
- UI_ThemeColor(TH_ACTIVE_VERT);
- glVertex3fv(dl ? co : bp->vec);
- UI_ThemeColor(color);
+ immAttrib4fv(color, active_color);
+ immVertex3fv(pos, dl ? co : bp->vec);
}
else if ((bp->f1 & SELECT) == sel) {
- glVertex3fv(dl ? co : bp->vec);
+ immAttrib4fv(color, draw_color);
+ immVertex3fv(pos, dl ? co : bp->vec);
}
}
}
@@ -2375,27 +2356,26 @@ static void lattice_draw_verts(Lattice *lt, DispList *dl, BPoint *actbp, short s
}
}
- glEnd();
+ immEnd();
}
-static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol)
+static void drawlattice__point(Lattice *lt, DispList *dl, int u, int v, int w, int actdef_wcol,
+ unsigned int pos, unsigned int color)
{
int index = ((w * lt->pntsv + v) * lt->pntsu) + u;
if (actdef_wcol) {
float col[3];
MDeformWeight *mdw = defvert_find_index(lt->dvert + index, actdef_wcol - 1);
-
weight_to_rgb(col, mdw ? mdw->weight : 0.0f);
- glColor3fv(col);
-
+ immAttrib3fv(color, col);
}
if (dl) {
- glVertex3fv(&dl->verts[index * 3]);
+ immVertex3fv(pos, &dl->verts[index * 3]);
}
else {
- glVertex3fv(lt->def[index].vec);
+ immVertex3fv(pos, lt->def[index].vec);
}
}
@@ -2443,7 +2423,7 @@ static void ensure_curve_cache(Scene *scene, Object *object)
#endif
/* lattice color is hardcoded, now also shows weightgroup values in edit mode */
-static void drawlattice(View3D *v3d, Object *ob)
+static void drawlattice(View3D *v3d, Object *ob, const short dflag, const unsigned char ob_wire_col[4])
{
Lattice *lt = ob->data;
DispList *dl;
@@ -2456,15 +2436,37 @@ static void drawlattice(View3D *v3d, Object *ob)
if (is_edit) {
lt = lt->editlatt->latt;
- UI_ThemeColor(TH_WIRE_EDIT);
-
if (ob->defbase.first && lt->dvert) {
actdef_wcol = ob->actdef;
}
}
+ VertexFormat *format = immVertexFormat();
+ unsigned int color, pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (actdef_wcol) {
+ color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (is_edit) {
+ immUniformThemeColor(TH_WIRE_EDIT);
+ }
+ else {
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ immUniformColor3ubv(ob_wire_col);
+ }
+ else {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ }
+ }
+ }
+
glLineWidth(1.0f);
- glBegin(GL_LINES);
+ immBeginAtMost(GL_LINES, lt->pntsw * lt->pntsv * lt->pntsu * 6);
+
for (w = 0; w < lt->pntsw; w++) {
int wxt = (w == 0 || w == lt->pntsw - 1);
for (v = 0; v < lt->pntsv; v++) {
@@ -2473,30 +2475,40 @@ static void drawlattice(View3D *v3d, Object *ob)
int uxt = (u == 0 || u == lt->pntsu - 1);
if (w && ((uxt || vxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v, w - 1, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
if (v && ((uxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u, v - 1, w, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
if (u && ((vxt || wxt) || !(lt->flag & LT_OUTSIDE))) {
- drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol);
- drawlattice__point(lt, dl, u, v, w, actdef_wcol);
+ drawlattice__point(lt, dl, u - 1, v, w, actdef_wcol, pos, color);
+ drawlattice__point(lt, dl, u, v, w, actdef_wcol, pos, color);
}
}
}
}
- glEnd();
+
+ immEnd();
+ immUnbindProgram();
if (is_edit) {
BPoint *actbp = BKE_lattice_active_point_get(lt);
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
-
- lattice_draw_verts(lt, dl, actbp, 0);
- lattice_draw_verts(lt, dl, actbp, 1);
-
+
+ VertexFormat *v_format = immVertexFormat();
+ unsigned int v_pos = add_attrib(v_format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int v_color = add_attrib(v_format, "color", GL_FLOAT, 4, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+
+ lattice_draw_verts(lt, dl, actbp, 0, v_pos, v_color);
+ lattice_draw_verts(lt, dl, actbp, 1, v_pos, v_color);
+
+ immUnbindProgram();
+
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
}
@@ -2510,6 +2522,7 @@ typedef struct drawDMVertSel_userData {
int active;
unsigned char *col[3]; /* (base, sel, act) */
char sel_prev;
+ unsigned int pos, color;
} drawDMVertSel_userData;
static void drawSelectedVertices__mapFunc(void *userData, int index, const float co[3],
@@ -2521,17 +2534,18 @@ static void drawSelectedVertices__mapFunc(void *userData, int index, const float
if (!(mv->flag & ME_HIDE)) {
const char sel = (index == data->active) ? 2 : (mv->flag & SELECT);
if (sel != data->sel_prev) {
- glColor3ubv(data->col[sel]);
+ immAttrib3ubv(data->color, data->col[sel]);
data->sel_prev = sel;
}
- glVertex3fv(co);
+ immVertex3fv(data->pos, co);
}
}
static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
{
drawDMVertSel_userData data;
+ VertexFormat *format = immVertexFormat();
/* TODO define selected color */
unsigned char base_col[3] = {0x0, 0x0, 0x0};
@@ -2546,9 +2560,18 @@ static void drawSelectedVertices(DerivedMesh *dm, Mesh *me)
data.col[1] = sel_col;
data.col[2] = act_col;
- glBegin(GL_POINTS);
+ data.color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ immBeginAtMost(GL_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, drawSelectedVertices__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* ************** DRAW MESH ****************** */
@@ -2595,25 +2618,34 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, const float
copy_v3_v3(n, no);
}
- glVertex3fv(cent);
- glVertex3f(cent[0] + n[0] * data->normalsize,
- cent[1] + n[1] * data->normalsize,
- cent[2] + n[2] * data->normalsize);
+ immVertex3fv(data->pos, cent);
+ immVertex3f(data->pos, cent[0] + n[0] * data->normalsize,
+ cent[1] + n[1] * data->normalsize,
+ cent[2] + n[2] * data->normalsize);
}
}
-static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_face_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
+ VertexFormat *format = immVertexFormat();
drawDMNormal_userData data;
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ if (dm->getNumPolys(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
+
+ immBeginAtMost(GL_LINES, dm->getNumPolys(dm) * 2);
dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static void draw_dm_face_centers__mapFunc(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
@@ -2624,16 +2656,28 @@ static void draw_dm_face_centers__mapFunc(void *userData, int index, const float
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) &&
(BM_elem_flag_test(efa, BM_ELEM_SELECT) == data->select))
{
- glVertex3fv(cent);
+ immVertex3fv(data->pos, cent);
}
}
-static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select)
+static void draw_dm_face_centers(BMEditMesh *em, DerivedMesh *dm, bool select, const unsigned char fcol[3])
{
- drawBMSelect_userData data = {em->bm, select};
+ VertexFormat *format = immVertexFormat();
+
+ drawBMSelect_userData data;
+ data.bm = em->bm;
+ data.select = select;
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (dm->getNumPolys(dm) == 0) return;
- glBegin(GL_POINTS);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(fcol);
+
+ immBeginAtMost(GL_POINTS, dm->getNumPolys(dm));
dm->foreachMappedFaceCenter(dm, draw_dm_face_centers__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3])
@@ -2660,71 +2704,83 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, const float
copy_v3_v3(n, no);
}
- glVertex3fv(co);
- glVertex3f(co[0] + n[0] * data->normalsize,
- co[1] + n[1] * data->normalsize,
- co[2] + n[2] * data->normalsize);
+ immVertex3fv(data->pos, co);
+ immVertex3f(data->pos, co[0] + n[0] * data->normalsize,
+ co[1] + n[1] * data->normalsize,
+ co[2] + n[2] * data->normalsize);
}
}
-static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_vert_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
drawDMNormal_userData data;
+ VertexFormat *format = immVertexFormat();
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
+
+ immBeginAtMost(GL_LINES, dm->getNumVerts(dm) * 2);
dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
-/* Draw verts with color set based on selection */
-static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
- const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+static void draw_dm_verts_skin_root__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
{
drawDMVerts_userData *data = userData;
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
/* skin nodes: draw a red circle around the root node(s) */
- if (data->cd_vskin_offset != -1) {
- const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
- if (vs->flag & MVERT_SKIN_ROOT) {
- float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
- glEnd();
-
- glColor4ubv(data->th_skin_root);
- drawcircball(GL_LINES, co, radius, data->imat);
-
- glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
- glBegin(GL_POINTS);
- }
+ const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, data->cd_vskin_offset);
+ if (vs->flag & MVERT_SKIN_ROOT) {
+ float radius = (vs->radius[0] + vs->radius[1]) * 0.5f;
+ imm_drawcircball(co, radius, data->imat, data->pos);
}
+ }
+}
+/* Draw verts with color set based on selection */
+static void draw_dm_verts__mapFunc(void *userData, int index, const float co[3],
+ const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
+{
+ drawDMVerts_userData *data = userData;
+ BMVert *eve = BM_vert_at_index(data->bm, index);
+
+ if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN) && BM_elem_flag_test(eve, BM_ELEM_SELECT) == data->sel) {
/* draw active in a different color - no need to stop/start point drawing for this :D */
if (eve == data->eve_act) {
- glColor4ubv(data->th_editmesh_active);
- glVertex3fv(co);
-
- /* back to regular vertex color */
- glColor4ubv(data->sel ? data->th_vertex_select : data->th_vertex);
+ immAttrib4ubv(data->color, data->th_editmesh_active);
+ immVertex3fv(data->pos, co);
}
else {
- glVertex3fv(co);
+ immAttrib4ubv(data->color, data->sel ? data->th_vertex_select : data->th_vertex);
+ immVertex3fv(data->pos, co);
}
}
}
static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVert *eve_act,
- RegionView3D *rv3d)
+ RegionView3D *rv3d, const unsigned char col[4])
{
+ VertexFormat *format = immVertexFormat();
+
drawDMVerts_userData data;
data.sel = sel;
data.eve_act = eve_act;
data.bm = em->bm;
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data.color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
/* Cache theme values */
UI_GetThemeColor4ubv(TH_EDITMESH_ACTIVE, data.th_editmesh_active);
@@ -2732,16 +2788,37 @@ static void draw_dm_verts(BMEditMesh *em, DerivedMesh *dm, const char sel, BMVer
UI_GetThemeColor4ubv(TH_VERTEX, data.th_vertex);
UI_GetThemeColor4ubv(TH_SKIN_ROOT, data.th_skin_root);
- /* For skin root drawing */
- data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
+ /* Set correct alpha */
+ data.th_editmesh_active[3] = data.th_vertex_select[3] = data.th_vertex[3] = data.th_skin_root[3] = col[3];
+
/* view-aligned matrix */
mul_m4_m4m4(data.imat, rv3d->viewmat, em->ob->obmat);
invert_m4(data.imat);
+ if (dm->getNumVerts(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, draw_dm_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
+
+ /* For skin root drawing */
+ data.cd_vskin_offset = CustomData_get_offset(&em->bm->vdata, CD_MVERT_SKIN);
+
+ if (data.cd_vskin_offset != -1) {
+ data.pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4ubv(data.th_skin_root);
+
+ dm->foreachMappedVert(dm, draw_dm_verts_skin_root__mapFunc, &data, DM_FOREACH_NOP);
+
+ immUnbindProgram();
+ }
}
/* Draw edges with color set based on selection */
@@ -3047,24 +3124,32 @@ static void draw_dm_loop_normals__mapFunc(void *userData, int vertex_index, int
}
mul_v3_fl(vec, data->normalsize);
add_v3_v3(vec, co);
- glVertex3fv(co);
- glVertex3fv(vec);
+ immVertex3fv(data->pos, co);
+ immVertex3fv(data->pos, vec);
}
}
}
-static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm)
+static void draw_dm_loop_normals(BMEditMesh *em, Scene *scene, Object *ob, DerivedMesh *dm, int theme_id)
{
drawDMNormal_userData data;
data.bm = em->bm;
data.normalsize = scene->toolsettings->normalsize;
+ data.pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (dm->getNumLoops(dm) == 0) return;
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(theme_id);
calcDrawDMNormalScale(ob, &data);
- glBegin(GL_LINES);
+ immBeginAtMost(GL_LINES, dm->getNumLoops(dm) * 2);
dm->foreachMappedLoop(dm, draw_dm_loop_normals__mapFunc, &data, DM_FOREACH_USE_NORMAL);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* Draw faces with color set based on selection
@@ -3211,8 +3296,10 @@ static void draw_dm_bweights__mapFunc(void *userData, int index, const float co[
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
const float bweight = BM_ELEM_CD_GET_FLOAT(eve, data->cd_layer_offset);
if (bweight != 0.0f) {
- UI_ThemeColorBlend(TH_VERTEX, TH_VERTEX_BEVEL, bweight);
- glVertex3fv(co);
+ unsigned char col[3];
+ UI_GetThemeColorBlend3ubv(TH_VERTEX, TH_VERTEX_BEVEL, bweight, col);
+ immAttrib3ubv(data->col, col);
+ immVertex3fv(data->pos, co);
}
}
}
@@ -3226,11 +3313,21 @@ static void draw_dm_bweights(BMEditMesh *em, Scene *scene, DerivedMesh *dm)
data.bm = em->bm;
data.cd_layer_offset = CustomData_get_offset(&em->bm->vdata, CD_BWEIGHT);
+ /* is that ever true? */
if (data.cd_layer_offset != -1) {
+ VertexFormat *format = immVertexFormat();
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data.col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) + 2.0f);
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, draw_dm_bweights__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
}
else {
@@ -3291,15 +3388,12 @@ static void draw_em_fancy_verts(Scene *scene, View3D *v3d, Object *obedit,
}
if (ts->selectmode & SCE_SELECT_VERTEX) {
- glPointSize(size);
- glColor4ubv(col);
- draw_dm_verts(em, cageDM, sel, eve_act, rv3d);
+ draw_dm_verts(em, cageDM, sel, eve_act, rv3d, col);
}
if (check_ob_drawface_dot(scene, v3d, obedit->dt)) {
glPointSize(fsize);
- glColor4ubv(fcol);
- draw_dm_face_centers(em, cageDM, sel);
+ draw_dm_face_centers(em, cageDM, sel, fcol);
}
if (pass == 0) {
@@ -3416,11 +3510,9 @@ static void draw_em_measure_stats(ARegion *ar, View3D *v3d, Object *ob, BMEditMe
if (me->drawflag & (ME_DRAWEXTRA_EDGELEN | ME_DRAWEXTRA_EDGEANG)) {
BoundBox bb;
- bglMats mats = {{0}};
const rcti rect = {0, ar->winx, 0, ar->winy};
- view3d_get_transformation(ar, ar->regiondata, em->ob, &mats);
- ED_view3d_clipping_calc(&bb, clip_planes, &mats, &rect);
+ ED_view3d_clipping_calc(&bb, clip_planes, ar, em->ob, &rect);
}
if (me->drawflag & ME_DRAWEXTRA_EDGELEN) {
@@ -3784,7 +3876,7 @@ static DMDrawOption draw_em_fancy__setGLSLFaceOpts(void *userData, int index)
}
}
-static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
+static void draw_em_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d,
Object *ob, BMEditMesh *em, DerivedMesh *cageDM, DerivedMesh *finalDM, const char dt)
{
@@ -3822,7 +3914,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
else if (check_object_draw_texture(scene, v3d, dt)) {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
+ if (draw_glsl_material(scene, sl, ob, v3d, dt)) {
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
finalDM->drawMappedFacesGLSL(finalDM, GPU_object_material_bind,
@@ -3832,7 +3924,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
glFrontFace(GL_CCW);
}
else {
- draw_mesh_textured(scene, v3d, rv3d, ob, finalDM, 0);
+ draw_mesh_textured(scene, sl, v3d, rv3d, ob, finalDM, 0);
}
}
else {
@@ -3995,16 +4087,13 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
draw_em_fancy_verts(scene, v3d, ob, em, cageDM, eve_act, rv3d);
if (me->drawflag & ME_DRAWNORMALS) {
- UI_ThemeColor(TH_NORMAL);
- draw_dm_face_normals(em, scene, ob, cageDM);
+ draw_dm_face_normals(em, scene, ob, cageDM, TH_NORMAL);
}
if (me->drawflag & ME_DRAW_VNORMALS) {
- UI_ThemeColor(TH_VNORMAL);
- draw_dm_vert_normals(em, scene, ob, cageDM);
+ draw_dm_vert_normals(em, scene, ob, cageDM, TH_VNORMAL);
}
if (me->drawflag & ME_DRAW_LNORMALS) {
- UI_ThemeColor(TH_LNORMAL);
- draw_dm_loop_normals(em, scene, ob, cageDM);
+ draw_dm_loop_normals(em, scene, ob, cageDM, TH_LNORMAL);
}
if ((me->drawflag & (ME_DRAWEXTRA_EDGELEN |
@@ -4036,7 +4125,7 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d,
#endif
}
-static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(v3d),
+static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *UNUSED(ar), View3D *UNUSED(v3d),
Object *UNUSED(ob), Mesh *me, BMEditMesh *UNUSED(em), DerivedMesh *UNUSED(cageDM), DerivedMesh *UNUSED(finalDM), const char UNUSED(dt))
{
/* for now... something simple! */
@@ -4074,10 +4163,12 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
Batch_draw(surface);
if (GLEW_VERSION_3_2) {
+#if 0
Batch *overlay = BKE_mesh_batch_cache_get_overlay_edges(me);
Batch_set_builtin_program(overlay, GPU_SHADER_EDGES_OVERLAY);
Batch_Uniform2f(overlay, "viewportSize", ar->winx, ar->winy);
Batch_draw(overlay);
+#endif
#if 0 /* TODO: use this SIMPLE variant for pure triangle meshes */
Batch_set_builtin_program(surface, GPU_SHADER_EDGES_OVERLAY_SIMPLE);
@@ -4105,7 +4196,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
Batch *verts = MBC_get_all_verts(me);
glEnable(GL_BLEND);
- Batch_set_builtin_program(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+ Batch_set_builtin_program(verts, GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
Batch_Uniform4f(verts, "color", 0.0f, 0.0f, 0.0f, 1.0f);
Batch_Uniform1f(verts, "size", UI_GetThemeValuef(TH_VERTEX_SIZE) * 1.5f);
Batch_draw(verts);
@@ -4116,7 +4207,7 @@ static void draw_em_fancy_new(Scene *UNUSED(scene), ARegion *ar, View3D *UNUSED(
/* Mesh drawing routines */
-void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) /* LEGACY */
+void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm, const unsigned char ob_wire_col[4]) /* LEGACY */
{
if ((v3d->transp == false) && /* not when we draw the transparent pass */
(ob->mode & OB_MODE_ALL_PAINT) == false) /* not when painting (its distracting) - campbell */
@@ -4124,6 +4215,8 @@ void draw_mesh_object_outline(View3D *v3d, Object *ob, DerivedMesh *dm) /* LEGAC
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
glDepthMask(GL_FALSE);
+ if (ob_wire_col) glColor4ubv(ob_wire_col);
+
/* if transparent, we cannot draw the edges for solid select... edges
* have no material info. GPU_object_material_visible will skip the
* transparent faces */
@@ -4188,11 +4281,11 @@ static bool object_is_halo(Scene *scene, Object *ob)
return (ma && (ma->material_type == MA_TYPE_HALO) && !BKE_scene_use_new_shading_nodes(scene));
}
-static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static void draw_mesh_fancy(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
#ifdef WITH_GAMEENGINE
- Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object;
+ Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object;
#else
Object *ob = base->object;
#endif
@@ -4200,7 +4293,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
eWireDrawMode draw_wire = OBDRAW_WIRE_OFF;
bool /* no_verts,*/ no_edges, no_faces;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- const bool is_obact = (ob == OBACT);
+ const bool is_obact = (ob == OBACT_NEW);
int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
if (!dm)
@@ -4236,7 +4329,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (dt == OB_BOUNDBOX) {
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else if ((no_faces && no_edges) ||
((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
@@ -4258,15 +4351,15 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
!(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
(draw_wire == OBDRAW_WIRE_OFF))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
- if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
+ if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
Paint *p;
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
GPUVertexAttribs gattribs;
float planes[4][4];
float (*fpl)[4] = NULL;
@@ -4274,7 +4367,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4299,7 +4392,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
draw_mesh_face_select(rv3d, me, dm, false);
}
else {
- draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
+ draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags);
}
if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) {
@@ -4329,7 +4422,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
/* materials arent compatible with vertex colors */
@@ -4353,19 +4446,19 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
float planes[4][4];
float (*fpl)[4] = NULL;
const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4406,7 +4499,9 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (is_obact && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f);
+ float color[3];
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.15f, color);
+ glColor3fv(color);
}
else {
glColor3ubv(ob_wire_col);
@@ -4451,7 +4546,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
}
/* returns true if nothing was drawn, for detecting to draw an object center */
-static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static bool draw_mesh_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
@@ -4505,13 +4600,13 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
if (use_material) {
if (dt > OB_WIRE) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
}
}
- draw_em_fancy(scene, ar, v3d, ob, em, cageDM, finalDM, dt);
+ draw_em_fancy(scene, sl, ar, v3d, ob, em, cageDM, finalDM, dt);
if (use_material) {
GPU_end_object_materials();
@@ -4524,16 +4619,16 @@ static bool draw_mesh_object(Scene *scene, ARegion *ar, View3D *v3d, RegionView3
/* ob->bb was set by derived mesh system, do NULL check just to be sure */
if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
if (dt > OB_WIRE) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
if (dt == OB_SOLID || glsl) {
const bool check_alpha = check_alpha_pass(base);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl,
(check_alpha) ? &do_alpha_after : NULL);
}
}
- draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ draw_mesh_fancy(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
GPU_end_object_materials();
@@ -4595,18 +4690,18 @@ static void make_color_variations(const unsigned char base_ubyte[4], float low[4
high[3] = base[3];
}
-static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static void draw_mesh_fancy_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag, const bool other_obedit)
{
if (dflag & (DRAW_PICKING | DRAW_CONSTCOLOR)) {
/* too complicated! use existing methods */
/* TODO: move this into a separate depth pre-pass */
- draw_mesh_fancy(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ draw_mesh_fancy(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
return;
}
#ifdef WITH_GAMEENGINE
- Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, scene) : base->object;
+ Object *ob = (rv3d->rflag & RV3D_IS_GAME_ENGINE) ? BKE_object_lod_meshob_get(base->object, sl) : base->object;
#else
Object *ob = base->object;
#endif
@@ -4614,7 +4709,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
eWireDrawMode draw_wire = OBDRAW_WIRE_OFF; /* could be bool draw_wire_overlay */
bool no_edges, no_faces;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- const bool is_obact = (ob == OBACT);
+ const bool is_obact = (ob == OBACT_NEW);
int draw_flags = (is_obact && BKE_paint_select_face_test(ob)) ? DRAW_FACE_SELECT : 0;
if (!dm)
@@ -4655,7 +4750,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
if (dt == OB_BOUNDBOX) {
if (((v3d->flag2 & V3D_RENDER_OVERRIDE) && v3d->drawtype >= OB_WIRE) == 0)
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else if ((no_faces && no_edges) ||
((!is_obact || (ob->mode == OB_MODE_OBJECT)) && object_is_halo(scene, ob)))
@@ -4735,15 +4830,15 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
!(G.f & G_PICKSEL || (draw_flags & DRAW_FACE_SELECT)) &&
(draw_wire == OBDRAW_WIRE_OFF))
{
- draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
}
- if (draw_glsl_material(scene, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
+ if (draw_glsl_material(scene, sl, ob, v3d, dt) && !(draw_flags & DRAW_MODIFIERS_PREVIEW)) {
Paint *p;
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if ((v3d->flag2 & V3D_SHOW_SOLID_MATCAP) && ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
GPUVertexAttribs gattribs;
float planes[4][4];
float (*fpl)[4] = NULL;
@@ -4751,7 +4846,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4772,7 +4867,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
draw_mesh_face_select(rv3d, me, dm, false);
}
else {
- draw_mesh_textured(scene, v3d, rv3d, ob, dm, draw_flags);
+ draw_mesh_textured(scene, sl, v3d, rv3d, ob, dm, draw_flags);
}
if (draw_loose && !(draw_flags & DRAW_FACE_SELECT)) {
@@ -4802,7 +4897,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
(draw_wire == OBDRAW_WIRE_OFF) &&
(ob->sculpt == NULL))
{
- draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
}
/* materials arent compatible with vertex colors */
@@ -4827,19 +4922,19 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
(ob->sculpt == NULL))
{
/* TODO: move this into a separate pass */
- draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT));
+ draw_mesh_object_outline_new(v3d, rv3d, ob, me, (ob == OBACT_NEW));
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
- if (ob->sculpt && (p = BKE_paint_get_active(scene))) {
+ if (ob->sculpt && (p = BKE_paint_get_active(scene, sl))) {
float planes[4][4];
float (*fpl)[4] = NULL;
const bool fast = (p->flags & PAINT_FAST_NAVIGATE) && (rv3d->rflag & RV3D_NAVIGATING);
if (ob->sculpt->partial_redraw) {
if (ar->do_draw & RGN_DRAW_PARTIAL) {
- ED_sculpt_redraw_planes_get(planes, ar, rv3d, ob);
+ ED_sculpt_redraw_planes_get(planes, ar, ob);
fpl = planes;
ob->sculpt->partial_redraw = 0;
}
@@ -4914,7 +5009,7 @@ static void draw_mesh_fancy_new(Scene *scene, ARegion *ar, View3D *v3d, RegionVi
dm->release(dm);
}
-static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static bool draw_mesh_object_new(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
const char dt, const unsigned char ob_wire_col[4], const short dflag)
{
Object *ob = base->object;
@@ -4971,9 +5066,9 @@ static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionV
DM_update_materials(cageDM, ob);
}
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
}
draw_em_fancy_new(scene, ar, v3d, ob, me, em, cageDM, finalDM, dt);
@@ -4989,18 +5084,18 @@ static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionV
/* ob->bb was set by derived mesh system, do NULL check just to be sure */
if (me->totpoly <= 4 || (!ob->bb || ED_view3d_boundbox_clip(rv3d, ob->bb))) {
if (solid) {
- const bool glsl = draw_glsl_material(scene, ob, v3d, dt);
+ const bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
if (dt == OB_SOLID || glsl) {
const bool check_alpha = check_alpha_pass(base);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl,
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl,
(check_alpha) ? &do_alpha_after : NULL);
}
}
const bool other_obedit = obedit && (obedit != ob);
- draw_mesh_fancy_new(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
+ draw_mesh_fancy_new(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag, other_obedit);
GPU_end_object_materials();
@@ -5016,16 +5111,85 @@ static bool draw_mesh_object_new(Scene *scene, ARegion *ar, View3D *v3d, RegionV
/* ************** DRAW DISPLIST ****************** */
+static void drawDispListVerts(int dt, const void *data, unsigned int vert_ct, const unsigned char wire_col[3])
+{
+ VertexFormat format = {0};
+ unsigned int pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, vert_ct);
+
+ fillAttrib(vbo, pos_id, data);
+
+ Batch *batch = Batch_create(dt, vbo, NULL);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (wire_col) {
+ Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f);
+ }
+ Batch_draw(batch);
+ Batch_discard_all(batch);
+}
+
+/* convert dispList with elem indices to batch, only support triangles and quads
+ * XXX : This is a huge perf issue. We should cache the resulting batches inside the object instead.
+ * But new viewport will do it anyway
+ * TODO implement flat drawing */
+static void drawDispListElem(bool quads, bool UNUSED(smooth), const float *data, const float *ndata, unsigned int vert_ct,
+ const int *elem, unsigned int elem_ct, const unsigned char wire_col[3])
+{
+ VertexFormat format = {0};
+ int i;
+ const int *idx = elem;
+ unsigned int pos_id, nor_id;
+
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ if (ndata) {
+ nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ ElementListBuilder elb;
+ ElementListBuilder_init(&elb, GL_TRIANGLES, (quads) ? elem_ct * 2 : elem_ct, 0xffffffff);
+
+ if (quads) {
+ for (i = elem_ct; i; --i, idx += 4) {
+ add_triangle_vertices(&elb, idx[0], idx[1], idx[2]);
+ add_triangle_vertices(&elb, idx[0], idx[2], idx[3]);
+ }
+ }
+ else {
+ for (i = elem_ct; i; --i, idx += 3) {
+ add_triangle_vertices(&elb, idx[0], idx[1], idx[2]);
+ }
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, vert_ct);
+
+ fillAttrib(vbo, pos_id, data);
+
+ if (ndata) {
+ fillAttrib(vbo, nor_id, ndata);
+ }
+
+ Batch *batch = Batch_create(GL_TRIANGLES, vbo, ElementList_build(&elb));
+ Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ if (wire_col) {
+ Batch_Uniform4f(batch, "color", wire_col[0]/255.0f, wire_col[1]/255.0f, wire_col[2]/255.0f, 1.0f);
+ }
+ Batch_Uniform4f(batch, "color", 0.8f, 0.8f, 0.8f, 1.0f);
+ Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ Batch_draw(batch);
+ Batch_discard_all(batch);
+}
/**
* \param dl_type_mask Only draw types matching this mask.
* \return true when nothing was drawn
*/
-static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask)
+static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask, const unsigned char wire_col[3])
{
if (dlbase == NULL) return true;
- glEnableClientState(GL_VERTEX_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
for (DispList *dl = dlbase->first; dl; dl = dl->next) {
@@ -5036,83 +5200,70 @@ static bool drawDispListwire_ex(ListBase *dlbase, unsigned int dl_type_mask)
if ((dl_type_mask & (1 << dl->type)) == 0) {
continue;
}
-
+
const float *data = dl->verts;
int parts;
switch (dl->type) {
case DL_SEGM:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
-
for (parts = 0; parts < dl->parts; parts++)
- glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
-
+ drawDispListVerts(GL_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
break;
- case DL_POLY:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
+ case DL_POLY:
for (parts = 0; parts < dl->parts; parts++)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
-
+ drawDispListVerts(GL_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
break;
- case DL_SURF:
-
- glVertexPointer(3, GL_FLOAT, 0, data);
+ case DL_SURF:
for (parts = 0; parts < dl->parts; parts++) {
if (dl->flag & DL_CYCL_U)
- glDrawArrays(GL_LINE_LOOP, parts * dl->nr, dl->nr);
+ drawDispListVerts(GL_LINE_LOOP, data + (parts * dl->nr * 3), dl->nr, wire_col);
else
- glDrawArrays(GL_LINE_STRIP, parts * dl->nr, dl->nr);
+ drawDispListVerts(GL_LINE_STRIP, data + (parts * dl->nr * 3), dl->nr, wire_col);
}
+ float *data_aligned = MEM_mallocN(sizeof(float) * 3 * dl->parts, "aligned data");
for (int nr = 0; nr < dl->nr; nr++) {
int ofs = 3 * dl->nr;
+ int idx = 0;
data = (dl->verts) + 3 * nr;
parts = dl->parts;
- if (dl->flag & DL_CYCL_V) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
-
while (parts--) {
- glVertex3fv(data);
+ copy_v3_v3(data_aligned + idx, data);
data += ofs;
+ idx += 3;
}
- glEnd();
-#if 0
- /* (ton) this code crashes for me when resolv is 86 or higher... no clue */
- glVertexPointer(3, GL_FLOAT, sizeof(float) * 3 * dl->nr, data + 3 * nr);
- if (dl->flag & DL_CYCL_V)
- glDrawArrays(GL_LINE_LOOP, 0, dl->parts);
- else
- glDrawArrays(GL_LINE_STRIP, 0, dl->parts);
-#endif
+ if (dl->flag & DL_CYCL_V)
+ drawDispListVerts(GL_LINE_LOOP, data_aligned, dl->parts, wire_col);
+ else
+ drawDispListVerts(GL_LINE_STRIP, data_aligned, dl->parts, wire_col);
}
+
+ if (data_aligned)
+ MEM_freeN(data_aligned);
+
break;
case DL_INDEX3:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
+ drawDispListElem(false, true, dl->verts, NULL, dl->nr, dl->index, dl->parts, wire_col);
break;
case DL_INDEX4:
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
+ drawDispListElem(true, true, dl->verts, NULL, dl->nr, dl->index, dl->parts, wire_col);
break;
}
}
- glDisableClientState(GL_VERTEX_ARRAY);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
return false;
}
-static bool drawDispListwire(ListBase *dlbase, const short ob_type)
+static bool drawDispListwire(ListBase *dlbase, const short ob_type, const unsigned char wire_col[3])
{
unsigned int dl_mask = 0xffffffff;
@@ -5121,27 +5272,25 @@ static bool drawDispListwire(ListBase *dlbase, const short ob_type)
dl_mask &= ~((1 << DL_INDEX3) | (1 << DL_INDEX4));
}
- return drawDispListwire_ex(dlbase, dl_mask);
+ return drawDispListwire_ex(dlbase, dl_mask, wire_col);
}
static bool index3_nors_incr = true;
-static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
+static void drawDispListsolid(ListBase *lb, Object *ob, const short UNUSED(dflag),
const unsigned char ob_wire_col[4], const bool use_glsl)
{
GPUVertexAttribs gattribs;
if (lb == NULL) return;
- glEnableClientState(GL_VERTEX_ARRAY);
-
/* track current material, -1 for none (needed for lines) */
short col = -1;
DispList *dl = lb->first;
while (dl) {
const float *data = dl->verts;
- const float *ndata = dl->nors;
+ //const float *ndata = dl->nors;
switch (dl->type) {
case DL_SEGM:
@@ -5151,15 +5300,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = -1;
}
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- glColor3ubv(ob_wire_col);
-
- // glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- // glDrawArrays(GL_LINE_STRIP, 0, dl->nr);
- glBegin(GL_LINE_STRIP);
- for (int nr = dl->nr; nr; nr--, data += 3)
- glVertex3fv(data);
- glEnd();
+ drawDispListVerts(GL_LINE_STRIP, data, dl->nr, ob_wire_col);
}
break;
case DL_POLY:
@@ -5169,14 +5310,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = -1;
}
- /* for some reason glDrawArrays crashes here in half of the platforms (not osx) */
- //glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- //glDrawArrays(GL_LINE_LOOP, 0, dl->nr);
-
- glBegin(GL_LINE_LOOP);
- for (int nr = dl->nr; nr; nr--, data += 3)
- glVertex3fv(data);
- glEnd();
+ drawDispListVerts(GL_LINE_LOOP, data, dl->nr, ob_wire_col);
}
break;
case DL_SURF:
@@ -5186,15 +5320,8 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
GPU_object_material_bind(dl->col + 1, use_glsl ? &gattribs : NULL);
col = dl->col;
}
- /* FLAT/SMOOTH shading for surfaces */
- glShadeModel((dl->rt & CU_SMOOTH) ? GL_SMOOTH : GL_FLAT);
- glEnableClientState(GL_NORMAL_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glNormalPointer(GL_FLOAT, 0, dl->nors);
- glDrawElements(GL_QUADS, 4 * dl->totindex, GL_UNSIGNED_INT, dl->index);
- glDisableClientState(GL_NORMAL_ARRAY);
- glShadeModel(GL_SMOOTH);
+ drawDispListElem(true, (dl->rt & CU_SMOOTH), dl->verts, dl->nors, dl->nr * dl->parts, dl->index, dl->totindex, ob_wire_col);
}
break;
@@ -5204,8 +5331,7 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = dl->col;
}
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
-
+#if 0
/* for polys only one normal needed */
if (index3_nors_incr) {
glEnableClientState(GL_NORMAL_ARRAY);
@@ -5213,11 +5339,13 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
}
else
glNormal3fv(ndata);
+#endif
+ drawDispListElem(false, (dl->rt & CU_SMOOTH), dl->verts, dl->nors, dl->nr, dl->index, dl->parts, ob_wire_col);
- glDrawElements(GL_TRIANGLES, 3 * dl->parts, GL_UNSIGNED_INT, dl->index);
-
+#if 0
if (index3_nors_incr)
glDisableClientState(GL_NORMAL_ARRAY);
+#endif
break;
@@ -5227,18 +5355,13 @@ static void drawDispListsolid(ListBase *lb, Object *ob, const short dflag,
col = dl->col;
}
- glEnableClientState(GL_NORMAL_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, dl->verts);
- glNormalPointer(GL_FLOAT, 0, dl->nors);
- glDrawElements(GL_QUADS, 4 * dl->parts, GL_UNSIGNED_INT, dl->index);
- glDisableClientState(GL_NORMAL_ARRAY);
+ drawDispListElem(true, true, dl->verts, dl->nors, dl->nr, dl->index, dl->parts, ob_wire_col);
break;
}
dl = dl->next;
}
- glDisableClientState(GL_VERTEX_ARRAY);
glFrontFace(GL_CCW);
if (col != -1) {
@@ -5253,7 +5376,7 @@ static void drawCurveDMWired(Object *ob)
}
/* return true when nothing was drawn */
-static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt)
+static bool drawCurveDerivedMesh(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, const char dt)
{
Object *ob = base->object;
DerivedMesh *dm = ob->derivedFinal;
@@ -5267,8 +5390,8 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
if (dt > OB_WIRE && dm->getNumPolys(dm)) {
- bool glsl = draw_glsl_material(scene, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
if (!glsl)
dm->drawFacesSolid(dm, NULL, 0, GPU_object_material_bind);
@@ -5289,7 +5412,7 @@ static bool drawCurveDerivedMesh(Scene *scene, View3D *v3d, RegionView3D *rv3d,
* Only called by #drawDispList
* \return true when nothing was drawn
*/
-static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static bool drawDispList_nobackface(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -5319,10 +5442,10 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (!render_only) {
/* when we have faces, only draw loose-wire */
if (has_faces) {
- drawDispListwire_ex(lb, (1 << DL_SEGM));
+ drawDispListwire_ex(lb, (1 << DL_SEGM), ob_wire_col);
}
else {
- drawDispListwire(lb, ob->type);
+ drawDispListwire(lb, ob->type, ob_wire_col);
}
}
@@ -5330,26 +5453,26 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
/* pass */
}
else {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, sl, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
if (cu->editnurb && cu->bevobj == NULL && cu->taperobj == NULL && cu->ext1 == 0.0f && cu->ext2 == 0.0f) {
- cpack(0);
- drawDispListwire(lb, ob->type);
+ unsigned char col[4] = {0, 0, 0, 0};
+ drawDispListwire(lb, ob->type, col);
}
}
index3_nors_incr = true;
}
else {
if (!render_only || BKE_displist_has_faces(lb)) {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
}
break;
@@ -5365,19 +5488,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (dl->nors == NULL) BKE_displist_normals_add(lb);
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, sl, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
else {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
break;
case OB_MBALL:
@@ -5390,19 +5513,19 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
if (solid) {
- if (draw_glsl_material(scene, ob, v3d, dt)) {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 1, NULL);
+ if (draw_glsl_material(scene, sl, ob, v3d, dt)) {
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 1, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, true);
GPU_end_object_materials();
}
else {
- GPU_begin_object_materials(v3d, rv3d, scene, ob, 0, NULL);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, 0, NULL);
drawDispListsolid(lb, ob, dflag, ob_wire_col, false);
GPU_end_object_materials();
}
}
else {
- return drawDispListwire(lb, ob->type);
+ return drawDispListwire(lb, ob->type, ob_wire_col);
}
}
break;
@@ -5410,7 +5533,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3
return false;
}
-static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static bool drawDispList(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
bool retval;
@@ -5426,7 +5549,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLega
ensure_curve_cache(scene, base->object);
#endif
- if (drawCurveDerivedMesh(scene, v3d, rv3d, base, dt) == false) {
+ if (drawCurveDerivedMesh(scene, sl, v3d, rv3d, base, dt) == false) {
retval = false;
}
else {
@@ -5442,7 +5565,7 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLega
glFrontFace(mode);
- retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ retval = drawDispList_nobackface(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
if (mode != GL_CCW) {
glFrontFace(GL_CCW);
@@ -5457,16 +5580,62 @@ static bool drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLega
}
/* *********** drawing for particles ************* */
-static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int select)
+/* stride : offset size in bytes
+ * col[4] : the color to use when *color is NULL, can be also NULL */
+static void draw_vertex_array(int dt, const float *vert, const float *nor, const float *color, int stride, int vert_ct, float col[4])
+{
+ VertexFormat format = {0};
+ unsigned int pos_id, nor_id, col_id;
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ if (nor) nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ if (color) col_id = add_attrib(&format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, vert_ct);
+
+ if (stride == 0) {
+ fillAttrib(vbo, pos_id, vert);
+ if (nor) fillAttrib(vbo, nor_id, nor);
+ if (color) fillAttrib(vbo, col_id, color);
+ }
+ else {
+ fillAttribStride(vbo, pos_id, stride, vert);
+ if (nor) fillAttribStride(vbo, nor_id, stride, nor);
+ if (color) fillAttribStride(vbo, col_id, stride, color);
+ }
+
+ Batch *batch = Batch_create(dt, vbo, NULL);
+ if (nor && color) {
+ Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR);
+ Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ }
+ else if (nor) {
+ Batch_set_builtin_program(batch, GPU_SHADER_SIMPLE_LIGHTING);
+ Batch_Uniform3f(batch, "light", 0.0f, 0.0f, 1.0f);
+ if (col) Batch_Uniform4fv(batch, "color", col);
+ }
+ else if (color) {
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ }
+ else {
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (col) Batch_Uniform4fv(batch, "color", col);
+ }
+ Batch_draw(batch);
+ Batch_discard_all(batch);
+}
+static void draw_particle_arrays_new(int draw_as, int ob_dt, int select,
+ const float *vert, const float *nor, const float *color,
+ int totpoint, float col[4])
{
/* draw created data arrays */
switch (draw_as) {
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
- glDrawArrays(GL_LINES, 0, 6 * totpoint);
+ draw_vertex_array(GL_LINES, vert, nor, color, 0, 6 * totpoint, col);
break;
case PART_DRAW_LINE:
- glDrawArrays(GL_LINES, 0, 2 * totpoint);
+ draw_vertex_array(GL_LINES, vert, nor, color, 0, 2 * totpoint, col);
break;
case PART_DRAW_BB:
if (ob_dt <= OB_WIRE || select)
@@ -5474,15 +5643,16 @@ static void draw_particle_arrays(int draw_as, int totpoint, int ob_dt, int selec
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glDrawArrays(GL_QUADS, 0, 4 * totpoint);
+ draw_vertex_array(GL_QUADS, vert, nor, color, 0, 4 * totpoint, col);
break;
default:
- glDrawArrays(GL_POINTS, 0, totpoint);
+ draw_vertex_array(GL_POINTS, vert, nor, color, 0, totpoint, col);
break;
}
}
static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize,
- float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd)
+ float imat[4][4], const float draw_line[2], ParticleBillboardData *bb, ParticleDrawData *pdd,
+ unsigned int pos)
{
float vec[3], vec2[3];
float *vd = NULL;
@@ -5592,7 +5762,7 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
}
case PART_DRAW_CIRC:
{
- drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
+ imm_drawcircball(state->co, pixsize, imat, pos);
break;
}
case PART_DRAW_BB:
@@ -5633,7 +5803,8 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
ParticleKey *state, int draw_as,
float imat[4][4], ParticleBillboardData *bb, ParticleDrawData *pdd,
- const float ct, const float pa_size, const float r_tilt, const float pixsize_scale)
+ const float ct, const float pa_size, const float r_tilt, const float pixsize_scale,
+ unsigned int pos)
{
ParticleSettings *part = psys->part;
float pixsize;
@@ -5664,7 +5835,7 @@ static void draw_particle_data(ParticleSystem *psys, RegionView3D *rv3d,
pixsize = ED_view3d_pixel_size(rv3d, state->co) * pixsize_scale;
- draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd);
+ draw_particle(state, draw_as, part->draw, pixsize, imat, part->draw_line, bb, pdd, pos);
}
/* unified drawing of all new particle systems draw types except dupli ob & group
* mostly tries to use vertex arrays for speed
@@ -5701,6 +5872,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
GLint polygonmode[2];
char numstr[32];
unsigned char tcol[4] = {0, 0, 0, 255};
+ unsigned int pos;
/* 1. */
if (part == NULL || !psys_check_enabled(ob, psys, G.is_rendering))
@@ -5762,16 +5934,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
copy_v3_v3(ma_col, &ma->r);
}
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glColor3ubv(tcol);
- }
-
timestep = psys_get_timestep(&sim);
if ((ob->flag & OB_FROMGROUP) != 0) {
float mat[4][4];
mul_m4_m4m4(mat, ob->obmat, psys->imat);
- glMultMatrixf(mat);
+ gpuMultMatrix3D(mat);
}
/* needed for text display */
@@ -5945,6 +6113,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
totpoint = pdd->totpoint; /* draw data is up to date */
}
else {
+ if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) {
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ imm_cpack(0xFFFFFF);
+ }
for (a = 0, pa = pars; a < totpart + totchild; a++, pa++) {
/* setup per particle individual stuff */
if (a < totpart) {
@@ -6015,7 +6188,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
draw_particle_data(psys, rv3d,
&state, draw_as, imat, &bb, psys->pdd,
- ct, pa_size, r_tilt, pixsize_scale);
+ ct, pa_size, r_tilt, pixsize_scale, pos);
totpoint++;
drawn = 1;
@@ -6027,7 +6200,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
draw_particle_data(psys, rv3d,
&state, draw_as, imat, &bb, psys->pdd,
- pa_time, pa_size, r_tilt, pixsize_scale);
+ pa_time, pa_size, r_tilt, pixsize_scale, pos);
totpoint++;
drawn = 1;
@@ -6049,7 +6222,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if (part->draw & PART_DRAW_SIZE) {
setlinestyle(3);
- drawcircball(GL_LINE_LOOP, state.co, pa_size, imat);
+ imm_drawcircball(state.co, pa_size, imat, pos);
setlinestyle(0);
}
@@ -6086,31 +6259,19 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
}
+ if ((draw_as == PART_DRAW_CIRC) || (part->draw & PART_DRAW_SIZE)) {
+ immUnbindProgram();
+ }
}
}
/* 6. */
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
- glEnableClientState(GL_VERTEX_ARRAY);
if (draw_as == PART_DRAW_PATH) {
ParticleCacheKey **cache, *path;
float *cdata2 = NULL;
- /* setup gl flags */
- if (1) { //ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
- }
-
- // XXX test
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
-
if (totchild && (part->draw & PART_DRAW_PARENT) == 0)
totpart = 0;
else if (psys->pathcache == NULL)
@@ -6121,41 +6282,28 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
path = cache[a];
if (path->segments > 0) {
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
-
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
+ if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) {
+ draw_vertex_array(GL_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL);
+ }
+ else {
+ float color[4];
+ rgba_uchar_to_float(color, tcol);
+ draw_vertex_array(GL_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color);
}
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
}
if (part->type == PART_HAIR) {
if (part->draw & PART_DRAW_GUIDE_HAIRS) {
DerivedMesh *hair_dm = psys->hair_out_dm;
-
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
+
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
if (pa->totkey > 1) {
HairKey *hkey = pa->hair;
- glVertexPointer(3, GL_FLOAT, sizeof(HairKey), hkey->world_co);
-
-#if 0 /* XXX use proper theme color here */
- UI_ThemeColor(TH_NORMAL);
-#else
- glColor3f(0.58f, 0.67f, 1.0f);
-#endif
-
- glDrawArrays(GL_LINE_STRIP, 0, pa->totkey);
+ /* XXX use proper theme color here */
+ float color[4] = {0.58f, 0.67f, 1.0f, 1.0f};
+ draw_vertex_array(GL_LINE_STRIP, hkey->world_co, NULL, NULL, sizeof(HairKey), pa->totkey, color);
}
}
@@ -6163,30 +6311,36 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
MVert *mvert = hair_dm->getVertArray(hair_dm);
int i;
- glColor3f(0.9f, 0.4f, 0.4f);
-
- glBegin(GL_LINES);
+ unsigned int pos_id = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3f(0.9f, 0.4f, 0.4f);
+
+ unsigned int count = 0;
for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
- for (i = 1; i < pa->totkey; ++i) {
- float v1[3], v2[3];
-
- copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
- copy_v3_v3(v2, mvert[pa->hair_index + i].co);
-
- mul_m4_v3(ob->obmat, v1);
- mul_m4_v3(ob->obmat, v2);
-
- glVertex3fv(v1);
- glVertex3fv(v2);
+ count += MAX2(pa->totkey - 1, 0);
+ }
+
+ if (count > 0) {
+ immBegin(GL_LINES, count * 2);
+ for (a = 0, pa = psys->particles; a < totpart; a++, pa++) {
+ for (i = 1; i < pa->totkey; ++i) {
+ float v1[3], v2[3];
+
+ copy_v3_v3(v1, mvert[pa->hair_index + i - 1].co);
+ copy_v3_v3(v2, mvert[pa->hair_index + i].co);
+
+ mul_m4_v3(ob->obmat, v1);
+ mul_m4_v3(ob->obmat, v2);
+
+ immVertex3fv(pos_id, v1);
+ immVertex3fv(pos_id, v2);
+ }
}
+ immEnd();
}
- glEnd();
+
+ immUnbindProgram();
}
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
}
if (part->draw & PART_DRAW_HAIR_GRID) {
@@ -6197,64 +6351,69 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
int *res = clmd->hair_grid_res;
int i;
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
-
+ unsigned int pos_id = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
if (select)
- UI_ThemeColor(TH_ACTIVE);
+ immUniformThemeColor(TH_ACTIVE);
else
- UI_ThemeColor(TH_WIRE);
- glBegin(GL_LINES);
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmin[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmin[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmin[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmin[2]);
+ immUniformThemeColor(TH_WIRE);
+
+ immBegin(GL_LINES, 24);
+ immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]);
- glVertex3f(gmin[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmax[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmax[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]);
- glVertex3f(gmin[0], gmin[1], gmin[2]); glVertex3f(gmin[0], gmin[1], gmax[2]);
- glVertex3f(gmax[0], gmin[1], gmin[2]); glVertex3f(gmax[0], gmin[1], gmax[2]);
- glVertex3f(gmin[0], gmax[1], gmin[2]); glVertex3f(gmin[0], gmax[1], gmax[2]);
- glVertex3f(gmax[0], gmax[1], gmin[2]); glVertex3f(gmax[0], gmax[1], gmax[2]);
- glEnd();
+ immVertex3f(pos_id, gmin[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmin[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmin[1], gmax[2]);
+ immVertex3f(pos_id, gmin[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmin[0], gmax[1], gmax[2]);
+ immVertex3f(pos_id, gmax[0], gmax[1], gmin[2]); immVertex3f(pos_id, gmax[0], gmax[1], gmax[2]);
+ immEnd();
if (select)
- UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
+ immUniformThemeColorShadeAlpha(TH_ACTIVE, 0, -100);
else
- UI_ThemeColorShadeAlpha(TH_WIRE, 0, -100);
- glEnable(GL_BLEND);
- glBegin(GL_LINES);
- for (i = 1; i < res[0] - 1; ++i) {
- float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
- glVertex3f(f, gmin[1], gmin[2]); glVertex3f(f, gmax[1], gmin[2]);
- glVertex3f(f, gmax[1], gmin[2]); glVertex3f(f, gmax[1], gmax[2]);
- glVertex3f(f, gmax[1], gmax[2]); glVertex3f(f, gmin[1], gmax[2]);
- glVertex3f(f, gmin[1], gmax[2]); glVertex3f(f, gmin[1], gmin[2]);
- }
- for (i = 1; i < res[1] - 1; ++i) {
- float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
- glVertex3f(gmin[0], f, gmin[2]); glVertex3f(gmax[0], f, gmin[2]);
- glVertex3f(gmax[0], f, gmin[2]); glVertex3f(gmax[0], f, gmax[2]);
- glVertex3f(gmax[0], f, gmax[2]); glVertex3f(gmin[0], f, gmax[2]);
- glVertex3f(gmin[0], f, gmax[2]); glVertex3f(gmin[0], f, gmin[2]);
- }
- for (i = 1; i < res[2] - 1; ++i) {
- float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
- glVertex3f(gmin[0], gmin[1], f); glVertex3f(gmax[0], gmin[1], f);
- glVertex3f(gmax[0], gmin[1], f); glVertex3f(gmax[0], gmax[1], f);
- glVertex3f(gmax[0], gmax[1], f); glVertex3f(gmin[0], gmax[1], f);
- glVertex3f(gmin[0], gmax[1], f); glVertex3f(gmin[0], gmin[1], f);
+ immUniformThemeColorShadeAlpha(TH_WIRE, 0, -100);
+
+ int count = 0;
+ count += MAX2(0, res[0] - 2) * 8;
+ count += MAX2(0, res[1] - 2) * 8;
+ count += MAX2(0, res[2] - 2) * 8;
+
+ if (count >= 2) {
+ glEnable(GL_BLEND);
+ immBegin(GL_LINES, count);
+ for (i = 1; i < res[0] - 1; ++i) {
+ float f = interpf(gmax[0], gmin[0], (float)i / (float)(res[0] - 1));
+ immVertex3f(pos_id, f, gmin[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmin[2]);
+ immVertex3f(pos_id, f, gmax[1], gmin[2]); immVertex3f(pos_id, f, gmax[1], gmax[2]);
+ immVertex3f(pos_id, f, gmax[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmax[2]);
+ immVertex3f(pos_id, f, gmin[1], gmax[2]); immVertex3f(pos_id, f, gmin[1], gmin[2]);
+ }
+ for (i = 1; i < res[1] - 1; ++i) {
+ float f = interpf(gmax[1], gmin[1], (float)i / (float)(res[1] - 1));
+ immVertex3f(pos_id, gmin[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmin[2]);
+ immVertex3f(pos_id, gmax[0], f, gmin[2]); immVertex3f(pos_id, gmax[0], f, gmax[2]);
+ immVertex3f(pos_id, gmax[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmax[2]);
+ immVertex3f(pos_id, gmin[0], f, gmax[2]); immVertex3f(pos_id, gmin[0], f, gmin[2]);
+ }
+ for (i = 1; i < res[2] - 1; ++i) {
+ float f = interpf(gmax[2], gmin[2], (float)i / (float)(res[2] - 1));
+ immVertex3f(pos_id, gmin[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmin[1], f);
+ immVertex3f(pos_id, gmax[0], gmin[1], f); immVertex3f(pos_id, gmax[0], gmax[1], f);
+ immVertex3f(pos_id, gmax[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmax[1], f);
+ immVertex3f(pos_id, gmin[0], gmax[1], f); immVertex3f(pos_id, gmin[0], gmin[1], f);
+ }
+ immEnd();
+ glDisable(GL_BLEND);
}
- glEnd();
- glDisable(GL_BLEND);
-
- glEnableClientState(GL_NORMAL_ARRAY);
- if ((dflag & DRAW_CONSTCOLOR) == 0)
- if (part->draw_col == PART_DRAW_COL_MAT)
- glEnableClientState(GL_COLOR_ARRAY);
+
+ immUnbindProgram();
}
}
}
@@ -6263,27 +6422,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cache = psys->childcache;
for (a = 0; a < totchild; a++) {
path = cache[a];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- if (1) { //ob_dt > OB_WIRE) {
- glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (part->draw_col == PART_DRAW_COL_MAT) {
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- }
- }
+ if (((dflag & DRAW_CONSTCOLOR) == 0) && (part->draw_col == PART_DRAW_COL_MAT)) {
+ draw_vertex_array(GL_LINE_STRIP, path->co, path->vel, path->col, sizeof(ParticleCacheKey), path->segments + 1, NULL);
+ }
+ else {
+ float color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ draw_vertex_array(GL_LINE_STRIP, path->co, path->vel, NULL, sizeof(ParticleCacheKey), path->segments + 1, color);
}
-
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
}
/* restore & clean up */
- if (1) { //ob_dt > OB_WIRE) {
- if (part->draw_col == PART_DRAW_COL_MAT)
- glDisableClientState(GL_COLOR_ARRAY);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- }
-
if (cdata2) {
MEM_freeN(cdata2);
cdata2 = NULL;
@@ -6303,19 +6452,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
else if (pdd && ELEM(draw_as, 0, PART_DRAW_CIRC) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
- /* enable point data array */
if (pdd->vdata) {
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, pdd->vdata);
- }
- else
- glDisableClientState(GL_VERTEX_ARRAY);
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
if (select) {
- UI_ThemeColor(TH_ACTIVE);
+ float color[4];
+ UI_GetThemeColor4fv(TH_ACTIVE, color);
if (part->draw_size)
glPointSize(part->draw_size + 2);
@@ -6324,48 +6465,39 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glLineWidth(3.0);
- draw_particle_arrays(draw_as, totpoint, ob_dt, 1);
+ draw_particle_arrays_new(draw_as, ob_dt, 1, pdd->vdata, NULL, NULL, totpoint, color);
}
- /* restore from select */
- glColor3fv(ma_col);
- }
-
- glPointSize(part->draw_size ? part->draw_size : 2.0);
- glLineWidth(1.0);
+ glPointSize(part->draw_size ? part->draw_size : 2.0);
+ glLineWidth(1.0);
- /* enable other data arrays */
- /* billboards are drawn this way */
- if (pdd->ndata && ob_dt > OB_WIRE) {
- glEnableClientState(GL_NORMAL_ARRAY);
- glNormalPointer(GL_FLOAT, 0, pdd->ndata);
- GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
- GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
- }
-
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if (pdd->cdata) {
- glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
+#if 0
+ /* enable other data arrays */
+ /* billboards are drawn this way */
+ if (pdd->ndata && ob_dt > OB_WIRE) {
+ GPU_basic_shader_colors(NULL, NULL, 0.0f, 1.0f);
+ GPU_basic_shader_bind(GPU_SHADER_LIGHTING | GPU_SHADER_USE_COLOR);
}
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ if (pdd->cdata) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, pdd->cdata);
+ }
+ }
+#endif
+
+ draw_particle_arrays_new(draw_as, ob_dt, 0, pdd->vdata, pdd->ndata, pdd->cdata, totpoint, NULL);
}
- draw_particle_arrays(draw_as, totpoint, ob_dt, 0);
pdd->flag |= PARTICLE_DRAW_DATA_UPDATED;
pdd->totpoint = totpoint;
}
if (pdd && pdd->vedata) {
- if ((dflag & DRAW_CONSTCOLOR) == 0) {
- glDisableClientState(GL_COLOR_ARRAY);
- cpack(0xC0C0C0);
- }
-
- glVertexPointer(3, GL_FLOAT, 0, pdd->vedata);
-
- glDrawArrays(GL_LINES, 0, 2 * totve);
+ float color[4] = {0.75f, 0.75f, 0.75f, 1.0f};
+ draw_vertex_array(GL_LINES, pdd->vedata, NULL, NULL, 0, 2 * totve, color);
}
glPolygonMode(GL_FRONT, polygonmode[0]);
@@ -6374,9 +6506,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* 7. */
GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
if (states)
MEM_freeN(states);
@@ -6400,14 +6529,14 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
if ((ob->flag & OB_FROMGROUP) != 0) {
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
}
-static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit)
+static void draw_update_ptcache_edit(Scene *scene, SceneLayer *sl, Object *ob, PTCacheEdit *edit)
{
if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED)
- PE_update_object(scene, ob, 0);
+ PE_update_object(scene, sl, ob, 0);
/* create path and child path cache if it doesn't exist already */
if (edit->pathcache == NULL)
@@ -6416,15 +6545,9 @@ static void draw_update_ptcache_edit(Scene *scene, Object *ob, PTCacheEdit *edit
static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
{
- ParticleCacheKey **cache, *path, *pkey;
- PTCacheEditPoint *point;
- PTCacheEditKey *key;
ParticleEditSettings *pset = PE_settings(scene);
- int i, k, totpoint = edit->totpoint, timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : 0;
- int totkeys = 1;
- float sel_col[3];
- float nosel_col[3];
- float *pathcol = NULL, *pcol;
+ const int totpoint = edit->totpoint;
+ const bool timed = (pset->flag & PE_FADE_TIME) ? pset->fade_frames : false;
if (edit->pathcache == NULL)
return;
@@ -6436,50 +6559,71 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
glDisable(GL_DEPTH_TEST);
/* get selection theme colors */
+ float sel_col[3], nosel_col[3];
UI_GetThemeColor3fv(TH_VERTEX_SELECT, sel_col);
UI_GetThemeColor3fv(TH_VERTEX, nosel_col);
/* draw paths */
- totkeys = (*edit->pathcache)->segments + 1;
+ const int totkeys = (*edit->pathcache)->segments + 1;
glEnable(GL_BLEND);
- pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
-
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
+ float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
if (pset->brushtype == PE_BRUSH_WEIGHT)
glLineWidth(2.0f);
- cache = edit->pathcache;
+ ParticleCacheKey **cache = edit->pathcache;
+ PTCacheEditPoint *point;
+ int i;
+
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
- path = cache[i];
- glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
+ ParticleCacheKey *path = cache[i];
+
+ VertexFormat format = {0};
+ unsigned int pos_id, col_id, col_comp;
+
+ col_comp = ((point->flag & PEP_HIDE) || timed) ? 4 : 3;
+
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ col_id = add_attrib(&format, "color", GL_FLOAT, col_comp, KEEP_FLOAT);
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, path->segments + 1);
+
+ fillAttribStride(vbo, pos_id, sizeof(ParticleCacheKey), path->co);
+
+ float *pcol = pathcol;
if (point->flag & PEP_HIDE) {
- for (k = 0, pcol = pathcol; k < totkeys; k++, pcol += 4) {
+ for (int k = 0; k < totkeys; k++, pcol += 4) {
copy_v3_v3(pcol, path->col);
pcol[3] = 0.25f;
}
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ fillAttrib(vbo, col_id, pathcol);
}
else if (timed) {
- for (k = 0, pcol = pathcol, pkey = path; k < totkeys; k++, pkey++, pcol += 4) {
+ ParticleCacheKey *pkey = path;
+ for (int k = 0; k < totkeys; k++, pkey++, pcol += 4) {
copy_v3_v3(pcol, pkey->col);
pcol[3] = 1.0f - fabsf((float)(CFRA) -pkey->time) / (float)pset->fade_frames;
}
- glColorPointer(4, GL_FLOAT, 4 * sizeof(float), pathcol);
+ fillAttrib(vbo, col_id, pathcol);
+ }
+ else {
+ /* FIXME: shader wants 4 color components but the cache only contains ParticleCacheKey
+ * So alpha is random */
+ fillAttribStride(vbo, col_id, sizeof(ParticleCacheKey), path->col);
}
- else
- glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
- glDrawArrays(GL_LINE_STRIP, 0, path->segments + 1);
+ Batch *batch = Batch_create(GL_LINE_STRIP, vbo, NULL);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ Batch_draw(batch);
+ Batch_discard_all(batch);
}
- if (pathcol) { MEM_freeN(pathcol); pathcol = pcol = NULL; }
-
+ if (pathcol) { MEM_freeN(pathcol); pathcol = NULL; }
/* draw edit vertices */
if (pset->selectmode != SCE_SELECT_PATH) {
@@ -6490,6 +6634,11 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
float *cd = NULL, *cdata = NULL;
int totkeys_visible = 0;
+ VertexFormat format = {0};
+ unsigned int pos_id, col_id;
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ col_id = add_attrib(&format, "color", GL_FLOAT, (timed ? 4 : 3), KEEP_FLOAT);
+
for (i = 0, point = edit->points; i < totpoint; i++, point++)
if (!(point->flag & PEP_HIDE))
totkeys_visible += point->totkey;
@@ -6504,7 +6653,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (point->flag & PEP_HIDE)
continue;
- for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
+ PTCacheEditKey *key = point->keys;
+ for (int k = 0; k < point->totkey; k++, key++) {
if (pd) {
copy_v3_v3(pd, key->co);
pd += 3;
@@ -6529,14 +6679,20 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (point->flag & PEP_HIDE || point->totkey == 0)
continue;
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, point->totkey);
+
if (point->keys->flag & PEK_USE_WCO)
- glVertexPointer(3, GL_FLOAT, sizeof(PTCacheEditKey), point->keys->world_co);
+ fillAttribStride(vbo, pos_id, sizeof(PTCacheEditKey), point->keys->world_co);
else
- glVertexPointer(3, GL_FLOAT, 3 * sizeof(float), pd);
+ fillAttrib(vbo, pos_id, pd);
- glColorPointer((timed ? 4 : 3), GL_FLOAT, (timed ? 4 : 3) * sizeof(float), cd);
+ fillAttrib(vbo, col_id, cd);
- glDrawArrays(GL_POINTS, 0, point->totkey);
+ Batch *batch = Batch_create(GL_POINTS, vbo, NULL);
+ Batch_set_builtin_program(batch, GPU_SHADER_3D_SMOOTH_COLOR);
+ Batch_draw(batch);
+ Batch_discard_all(batch);
pd += pd ? 3 * point->totkey : 0;
cd += (timed ? 4 : 3) * point->totkey;
@@ -6545,23 +6701,30 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (cdata) { MEM_freeN(cdata); cd = cdata = NULL; }
}
else if (pset->selectmode == SCE_SELECT_END) {
- glBegin(GL_POINTS);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos_id = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int col_id = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+ immBeginAtMost(GL_POINTS, totpoint);
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
if ((point->flag & PEP_HIDE) == 0 && point->totkey) {
- key = point->keys + point->totkey - 1;
- glColor3fv((key->flag & PEK_SELECT) ? sel_col : nosel_col);
+ PTCacheEditKey *key = point->keys + point->totkey - 1;
+ if ((key->flag & PEK_SELECT) != 0) {
+ immAttrib3fv(col_id, sel_col);
+ }
+ else {
+ immAttrib3fv(col_id, nosel_col);
+ }
/* has to be like this.. otherwise selection won't work, have try glArrayElement later..*/
- glVertex3fv((key->flag & PEK_USE_WCO) ? key->world_co : key->co);
+ immVertex3fv(pos_id, (key->flag & PEK_USE_WCO) ? key->world_co : key->co);
}
}
- glEnd();
+ immEnd();
+ immUnbindProgram();
}
}
glDisable(GL_BLEND);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_VERTEX_ARRAY);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -6574,130 +6737,137 @@ static void ob_draw_RE_motion(float com[3], float rotscale[3][3], float itw, flo
float tw = itw * drw_size;
float th = ith * drw_size;
- glBegin(GL_LINES);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ immBegin(GL_LINES, 30);
- glColor4ub(0x7F, 0x00, 0x00, 155);
+ immAttrib4ub(col, 0x7F, 0x00, 0x00, 155);
root[1] = root[2] = 0.0f;
root[0] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[1] = tip[2] = 0.0f;
tip[0] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[1] = 0.0f; root[2] = tw;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = 0.0f; root[2] = -tw;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = tw; root[2] = 0.0f;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[1] = -tw; root[2] = 0.0f;
root[0] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
- glColor4ub(0x00, 0x7F, 0x00, 155);
+ immAttrib4ub(col, 0x00, 0x7F, 0x00, 155);
root[0] = root[2] = 0.0f;
root[1] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[0] = tip[2] = 0.0f;
tip[1] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[2] = tw;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[2] = -tw;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = tw; root[2] = 0.0f;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = -tw; root[2] = 0.0f;
root[1] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
- glColor4ub(0x00, 0x00, 0x7F, 155);
+ immAttrib4ub(col, 0x00, 0x00, 0x7F, 155);
root[0] = root[1] = 0.0f;
root[2] = -drw_size;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
+ immVertex3fv(pos, root);
tip[0] = tip[1] = 0.0f;
tip[2] = drw_size;
mul_m3_v3(tr, tip);
add_v3_v3(tip, com);
- glVertex3fv(tip);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[1] = tw;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = 0.0f; root[1] = -tw;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = tw; root[1] = 0.0f;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
root[0] = -tw; root[1] = 0.0f;
root[2] = th;
mul_m3_v3(tr, root);
add_v3_v3(root, com);
- glVertex3fv(root);
- glVertex3fv(tip);
+ immVertex3fv(pos, root);
+ immVertex3fv(pos, tip);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
/* place to add drawers */
@@ -6706,7 +6876,7 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
{
if (nu->hide || hide_handles) return;
- if (nu->type == CU_BEZIER) {
+ if (nu->type == CU_BEZIER && nu->pntsu > 0) {
const float *fp;
@@ -6719,9 +6889,14 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
UI_GetThemeColor3ubv(basecol + a, handle_cols[a]);
}
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glLineWidth(1.0f);
- glBegin(GL_LINES);
+ immBeginAtMost(GL_LINES, nu->pntsu * 4);
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
@@ -6730,33 +6905,35 @@ static void drawhandlesN(Nurb *nu, const char sel, const bool hide_handles)
if ((bezt->f2 & SELECT) == sel) {
fp = bezt->vec[0];
- glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
- glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp + 3);
- glVertex3fv(fp + 6);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp + 3);
+ immVertex3fv(pos, fp + 6);
}
else if ((bezt->f1 & SELECT) == sel) {
fp = bezt->vec[0];
- glColor3ubv(handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h1, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
}
else if ((bezt->f3 & SELECT) == sel) {
fp = bezt->vec[1];
- glColor3ubv(handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immAttrib3ubv(col, handle_cols[MIN2(bezt->h2, TH_HANDLE_COL_TOT - 1)]);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
}
}
bezt++;
}
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
#undef TH_HANDLE_COL_TOT
@@ -6767,30 +6944,30 @@ static void drawhandlesN_active(Nurb *nu)
{
if (nu->hide) return;
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2.0f);
-
- glBegin(GL_LINES);
+ if (nu->type == CU_BEZIER && nu->pntsu > 0) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
+ glLineWidth(2.0f);
- if (nu->type == CU_BEZIER) {
+ immBeginAtMost(GL_LINES, nu->pntsu * 4);
BezTriple *bezt = nu->bezt;
int a = nu->pntsu;
while (a--) {
if (bezt->hide == 0) {
const float *fp = bezt->vec[0];
- glVertex3fv(fp);
- glVertex3fv(fp + 3);
+ immVertex3fv(pos, fp);
+ immVertex3fv(pos, fp + 3);
- glVertex3fv(fp + 3);
- glVertex3fv(fp + 6);
+ immVertex3fv(pos, fp + 3);
+ immVertex3fv(pos, fp + 6);
}
bezt++;
}
+ immEnd();
+ immUnbindProgram();
}
- glEnd();
-
- glColor3ub(0, 0, 0);
}
static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *vert)
@@ -6885,63 +7062,78 @@ static void drawvertsN(const Nurb *nurb, const bool hide_handles, const void *ve
static void editnurb_draw_active_poly(Nurb *nu)
{
- UI_ThemeColor(TH_ACTIVE_SPLINE);
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
+
glLineWidth(2.0f);
BPoint *bp = nu->bp;
for (int b = 0; b < nu->pntsv; b++) {
- if (nu->flagu & 1) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
+ if (nu->pntsu >= 2) {
+ if (nu->flagu & 1) immBegin(GL_LINE_LOOP, nu->pntsu);
+ else immBegin(GL_LINE_STRIP, nu->pntsu);
- for (int a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
+ for (int a = 0; a < nu->pntsu; a++, bp++) {
+ immVertex3fv(pos, bp->vec);
+ }
- glEnd();
+ immEnd();
+ }
}
- glColor3ub(0, 0, 0);
+ immUnbindProgram();
}
static void editnurb_draw_active_nurbs(Nurb *nu)
{
- UI_ThemeColor(TH_ACTIVE_SPLINE);
- glLineWidth(2.0f);
-
- glBegin(GL_LINES);
- BPoint *bp = nu->bp;
- for (int b = 0; b < nu->pntsv; b++) {
- BPoint *bp1 = bp;
- bp++;
+ if (nu->pntsv > 0) {
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_ACTIVE_SPLINE);
- for (int a = nu->pntsu - 1; a > 0; a--, bp++) {
- if (bp->hide == 0 && bp1->hide == 0) {
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ glLineWidth(2.0f);
+ // just quick guesstimate of how many verts to draw
+ int count = (nu->pntsu - 1) * nu->pntsv * 2;
+ if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2;
+ if (count < 2) return;
+
+ immBeginAtMost(GL_LINES, count);
+ BPoint *bp = nu->bp;
+ for (int b = 0; b < nu->pntsv; b++) {
+ BPoint *bp1 = bp;
+ bp++;
+
+ for (int a = nu->pntsu - 1; a > 0; a--, bp++) {
+ if (bp->hide == 0 && bp1->hide == 0) {
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
+ }
+ bp1 = bp;
}
- bp1 = bp;
}
- }
-
- if (nu->pntsv > 1) { /* surface */
- int ofs = nu->pntsu;
- for (int b = 0; b < nu->pntsu; b++) {
- BPoint *bp1 = nu->bp + b;
- bp = bp1 + ofs;
- for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) {
- if (bp->hide == 0 && bp1->hide == 0) {
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ if (nu->pntsv > 1) { /* surface */
+ int ofs = nu->pntsu;
+ for (int b = 0; b < nu->pntsu; b++) {
+ BPoint *bp1 = nu->bp + b;
+ bp = bp1 + ofs;
+ for (int a = nu->pntsv - 1; a > 0; a--, bp += ofs) {
+ if (bp->hide == 0 && bp1->hide == 0) {
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
+ }
+ bp1 = bp;
}
- bp1 = bp;
}
}
- }
- glEnd();
+ immEnd();
- glColor3ub(0, 0, 0);
+ immUnbindProgram();
+ }
}
static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
@@ -6949,6 +7141,9 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
BPoint *bp, *bp1;
int a, b;
Curve *cu = ob->data;
+ VertexFormat *format;
+ unsigned int pos, col;
+ unsigned char color[3];
int index = 0;
Nurb *nu = nurb;
@@ -6956,35 +7151,55 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (nu->hide == 0) {
switch (nu->type) {
case CU_POLY:
+ {
if (!sel && index == cu->actnu) {
/* we should draw active spline highlight below everything */
editnurb_draw_active_poly(nu);
}
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
glLineWidth(1.0f);
- UI_ThemeColor(TH_NURB_ULINE);
+ immUniformThemeColor(TH_NURB_ULINE);
bp = nu->bp;
for (b = 0; b < nu->pntsv; b++) {
- if (nu->flagu & 1) glBegin(GL_LINE_LOOP);
- else glBegin(GL_LINE_STRIP);
+ if (nu->pntsu >= 2) {
+ if (nu->flagu & 1) immBegin(GL_LINE_LOOP, nu->pntsu);
+ else immBegin(GL_LINE_STRIP, nu->pntsu);
- for (a = 0; a < nu->pntsu; a++, bp++) {
- glVertex3fv(bp->vec);
- }
+ for (a = 0; a < nu->pntsu; a++, bp++) {
+ immVertex3fv(pos, bp->vec);
+ }
- glEnd();
+ immEnd();
+ }
}
+ immUnbindProgram();
break;
+ }
case CU_NURBS:
+ {
if (!sel && index == cu->actnu) {
/* we should draw active spline highlight below everything */
editnurb_draw_active_nurbs(nu);
}
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ // just quick guesstimate of how many verts to draw
+ int count = (nu->pntsu - 1) * nu->pntsv * 2;
+ if (nu->pntsv > 1) count += (nu->pntsv - 1) * nu->pntsu * 2;
+ if (count < 2) return;
+
glLineWidth(1.0f);
- glBegin(GL_LINES);
+ immBeginAtMost(GL_LINES, count);
bp = nu->bp;
for (b = 0; b < nu->pntsv; b++) {
@@ -6994,10 +7209,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (bp->hide == 0 && bp1->hide == 0) {
if (sel) {
if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- UI_ThemeColor(TH_NURB_SEL_ULINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_SEL_ULINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
else {
@@ -7005,10 +7220,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
/* pass */
}
else {
- UI_ThemeColor(TH_NURB_ULINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_ULINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
}
@@ -7025,10 +7240,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
if (bp->hide == 0 && bp1->hide == 0) {
if (sel) {
if ((bp->f1 & SELECT) && (bp1->f1 & SELECT)) {
- UI_ThemeColor(TH_NURB_SEL_VLINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_SEL_VLINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
else {
@@ -7036,10 +7251,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
/* pass */
}
else {
- UI_ThemeColor(TH_NURB_VLINE);
-
- glVertex3fv(bp->vec);
- glVertex3fv(bp1->vec);
+ UI_GetThemeColor3ubv(TH_NURB_VLINE, color);
+ immAttrib3ubv(col, color);
+ immVertex3fv(pos, bp->vec);
+ immVertex3fv(pos, bp1->vec);
}
}
}
@@ -7047,9 +7262,10 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
}
}
}
-
- glEnd();
+ immEnd();
+ immUnbindProgram();
break;
+ }
}
}
@@ -7059,8 +7275,8 @@ static void draw_editnurb_splines(Object *ob, Nurb *nurb, const bool sel)
}
static void draw_editnurb(
- Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base, Nurb *nurb,
- const char dt, const short dflag, const unsigned char ob_wire_col[4])
+ Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base, Nurb *nurb,
+ const char dt, const short dflag, const unsigned char UNUSED(ob_wire_col[4]))
{
ToolSettings *ts = scene->toolsettings;
Object *ob = base->object;
@@ -7072,9 +7288,8 @@ static void draw_editnurb(
/* DispList */
UI_GetThemeColor3ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, wire_col);
/* for shadows only show solid faces */
if (v3d->flag2 & V3D_RENDER_SHADOW)
@@ -7102,74 +7317,97 @@ static void draw_editnurb(
if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
- glColor3ubv(wire_col);
-
/* direction vectors for 3d curve paths
* when at its lowest, don't render normals */
if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) {
BevList *bl;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_WIRE_EDIT);
+
glLineWidth(1.0f);
+
+ int count = 0;
for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
- BevPoint *bevp = bl->bevpoints;
int nr = bl->nr;
int skip = nu->resolu / 16;
while (nr-- > 0) { /* accounts for empty bevel lists */
- const float fac = bevp->radius * ts->normalsize;
- float vec_a[3]; /* Offset perpendicular to the curve */
- float vec_b[3]; /* Delta along the curve */
-
- vec_a[0] = fac;
- vec_a[1] = 0.0f;
- vec_a[2] = 0.0f;
+ count += 4;
+ nr -= skip;
+ }
+ }
- vec_b[0] = -fac;
- vec_b[1] = 0.0f;
- vec_b[2] = 0.0f;
-
- mul_qt_v3(bevp->quat, vec_a);
- mul_qt_v3(bevp->quat, vec_b);
- add_v3_v3(vec_a, bevp->vec);
- add_v3_v3(vec_b, bevp->vec);
-
- madd_v3_v3fl(vec_a, bevp->dir, -fac);
- madd_v3_v3fl(vec_b, bevp->dir, -fac);
-
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec_a);
- glVertex3fv(bevp->vec);
- glVertex3fv(vec_b);
- glEnd();
+ if (count > 2) {
+ immBegin(GL_LINES, count);
+ for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) {
+ BevPoint *bevp = bl->bevpoints;
+ int nr = bl->nr;
+ int skip = nu->resolu / 16;
- bevp += skip + 1;
- nr -= skip;
+ while (nr-- > 0) { /* accounts for empty bevel lists */
+ const float fac = bevp->radius * ts->normalsize;
+ float vec_a[3]; /* Offset perpendicular to the curve */
+ float vec_b[3]; /* Delta along the curve */
+
+ vec_a[0] = fac;
+ vec_a[1] = 0.0f;
+ vec_a[2] = 0.0f;
+
+ vec_b[0] = -fac;
+ vec_b[1] = 0.0f;
+ vec_b[2] = 0.0f;
+
+ mul_qt_v3(bevp->quat, vec_a);
+ mul_qt_v3(bevp->quat, vec_b);
+ add_v3_v3(vec_a, bevp->vec);
+ add_v3_v3(vec_b, bevp->vec);
+
+ madd_v3_v3fl(vec_a, bevp->dir, -fac);
+ madd_v3_v3fl(vec_b, bevp->dir, -fac);
+
+ immVertex3fv(pos, vec_a);
+ immVertex3fv(pos, bevp->vec);
+ immVertex3fv(pos, bevp->vec);
+ immVertex3fv(pos, vec_b);
+
+ bevp += skip + 1;
+ nr -= skip;
+ }
}
+ immEnd();
}
+ immUnbindProgram();
}
- if (v3d->zbuf) glDepthFunc(GL_ALWAYS);
+ if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- drawvertsN(nu, hide_handles, vert);
+ drawvertsN(nurb, hide_handles, vert);
- if (v3d->zbuf) glDepthFunc(GL_LEQUAL);
+ if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
static void draw_editfont_textcurs(RegionView3D *rv3d, float textcurs[4][2])
{
- cpack(0);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
ED_view3d_polygon_offset(rv3d, -1.0);
set_inverted_drawing(1);
- glBegin(GL_QUADS);
- glVertex2fv(textcurs[0]);
- glVertex2fv(textcurs[1]);
- glVertex2fv(textcurs[2]);
- glVertex2fv(textcurs[3]);
- glEnd();
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ imm_cpack(0);
+ immBegin(GL_TRIANGLE_FAN, 4);
+ immVertex2fv(pos, textcurs[0]);
+ immVertex2fv(pos, textcurs[1]);
+ immVertex2fv(pos, textcurs[2]);
+ immVertex2fv(pos, textcurs[3]);
+ immEnd();
set_inverted_drawing(0);
ED_view3d_polygon_offset(rv3d, 0.0);
+ immUnbindProgram();
}
-static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static void draw_editfont(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -7183,15 +7421,17 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLeg
if (cu->flag & CU_FAST) {
cpack(0xFFFFFF);
set_inverted_drawing(1);
- drawDispList(scene, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
+ drawDispList(scene, sl, v3d, rv3d, base, OB_WIRE, dflag, ob_wire_col);
set_inverted_drawing(0);
}
else {
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
if (cu->linewidth != 0.0f) {
- UI_ThemeColor(TH_WIRE_EDIT);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColor(TH_WIRE_EDIT);
copy_v3_v3(vec1, ob->orig);
copy_v3_v3(vec2, ob->orig);
vec1[0] += cu->linewidth;
@@ -7199,31 +7439,35 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLeg
vec1[1] += cu->linedist * cu->fsize;
vec2[1] -= cu->lines * cu->linedist * cu->fsize;
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex2fv(vec1);
- glVertex2fv(vec2);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex2fv(pos, vec1);
+ immVertex2fv(pos, vec2);
+ immEnd();
setlinestyle(0);
+ immUnbindProgram();
}
setlinestyle(3);
for (int i = 0; i < cu->totbox; i++) {
if (cu->tb[i].w != 0.0f) {
- UI_ThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformThemeColor(i == (cu->actbox - 1) ? TH_ACTIVE : TH_WIRE);
vec1[0] = cu->xof + cu->tb[i].x;
vec1[1] = cu->yof + cu->tb[i].y + cu->fsize;
vec1[2] = 0.001;
- glBegin(GL_LINE_STRIP);
- glVertex3fv(vec1);
+ immBegin(GL_LINE_STRIP, 5);
+ immVertex3fv(pos, vec1);
vec1[0] += cu->tb[i].w;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[1] -= cu->tb[i].h;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[0] -= cu->tb[i].w;
- glVertex3fv(vec1);
+ immVertex3fv(pos, vec1);
vec1[1] += cu->tb[i].h;
- glVertex3fv(vec1);
- glEnd();
+ immVertex3fv(pos, vec1);
+ immEnd();
+ immUnbindProgram();
}
}
setlinestyle(0);
@@ -7233,7 +7477,9 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLeg
const int seltot = selend - selstart;
float selboxw;
- cpack(0xffffff);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ imm_cpack(0xffffff);
set_inverted_drawing(1);
for (int i = 0; i <= seltot; i++) {
EditFontSelBox *sb = &ef->selboxes[i];
@@ -7252,20 +7498,20 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLeg
/* fill in xy below */
tvec[2] = 0.001;
- glBegin(GL_QUADS);
+ immBegin(GL_TRIANGLE_FAN, 4);
if (sb->rot == 0.0f) {
copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x + selboxw, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x + selboxw, sb->y + sb->h);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, sb->x, sb->y + sb->h);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
}
else {
float mat[2][2];
@@ -7273,27 +7519,28 @@ static void draw_editfont(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLeg
angle_to_mat2(mat, sb->rot);
copy_v2_fl2(tvec, sb->x, sb->y);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, selboxw, 0.0f);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, selboxw, sb->h);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
copy_v2_fl2(tvec, 0.0f, sb->h);
mul_m2v2(mat, tvec);
add_v2_v2(tvec, &sb->x);
- glVertex3fv(tvec);
+ immVertex3fv(pos, tvec);
}
- glEnd();
+ immEnd();
}
set_inverted_drawing(0);
+ immUnbindProgram();
}
}
@@ -7352,7 +7599,7 @@ static void draw_empty_cone(float size, unsigned pos)
#undef NSEGMENTS
}
-static void drawspiral(const float cent[3], float rad, float tmat[4][4], int start)
+static void drawspiral(unsigned int pos, const float cent[3], float rad, float tmat[4][4], int start)
{
float vec[3], vx[3], vy[3];
const float tot_inv = 1.0f / (float)CIRCLE_RESOL;
@@ -7368,11 +7615,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
mul_v3_v3fl(vx, tmat[0], rad);
mul_v3_v3fl(vy, tmat[1], rad);
- glBegin(GL_LINE_STRIP);
+ immBegin(GL_LINE_STRIP, CIRCLE_RESOL + 1);
if (inverse == 0) {
copy_v3_v3(vec, cent);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
for (a = 0; a < CIRCLE_RESOL; a++) {
if (a + start >= CIRCLE_RESOL)
@@ -7386,7 +7633,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
}
}
else {
@@ -7398,7 +7645,7 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
for (a = 0; a < CIRCLE_RESOL; a++) {
if (a + start >= CIRCLE_RESOL)
@@ -7411,11 +7658,11 @@ static void drawspiral(const float cent[3], float rad, float tmat[4][4], int sta
vec[0] = cent[0] + (x * vx[0] + y * vy[0]);
vec[1] = cent[1] + (x * vx[1] + y * vy[1]);
vec[2] = cent[2] + (x * vx[2] + y * vy[2]);
- glVertex3fv(vec);
+ immVertex3fv(pos, vec);
}
}
- glEnd();
+ immEnd();
}
/* draws a circle on x-z plane given the scaling of the circle, assuming that
@@ -7436,29 +7683,6 @@ static void drawcircle_size(float size, unsigned pos)
}
/* needs fixing if non-identity matrix used */
-static void drawtube(const float vec[3], float radius, float height, float tmat[4][4])
-{
- float cur[3];
- drawcircball(GL_LINE_LOOP, vec, radius, tmat);
-
- copy_v3_v3(cur, vec);
- cur[2] += height;
-
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
-
- glBegin(GL_LINES);
- glVertex3f(vec[0] + radius, vec[1], vec[2]);
- glVertex3f(cur[0] + radius, cur[1], cur[2]);
- glVertex3f(vec[0] - radius, vec[1], vec[2]);
- glVertex3f(cur[0] - radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1] + radius, vec[2]);
- glVertex3f(cur[0], cur[1] + radius, cur[2]);
- glVertex3f(vec[0], vec[1] - radius, vec[2]);
- glVertex3f(cur[0], cur[1] - radius, cur[2]);
- glEnd();
-}
-
-/* needs fixing if non-identity matrix used */
static void imm_drawtube(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
{
float cur[3];
@@ -7482,29 +7706,6 @@ static void imm_drawtube(const float vec[3], float radius, float height, float t
}
/* needs fixing if non-identity matrix used */
-static void drawcone(const float vec[3], float radius, float height, float tmat[4][4])
-{
- float cur[3];
-
- copy_v3_v3(cur, vec);
- cur[2] += height;
-
- drawcircball(GL_LINE_LOOP, cur, radius, tmat);
-
- glBegin(GL_LINES);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0] + radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0] - radius, cur[1], cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
-
- glVertex3f(cur[0], cur[1] + radius, cur[2]);
- glVertex3f(vec[0], vec[1], vec[2]);
- glVertex3f(cur[0], cur[1] - radius, cur[2]);
- glEnd();
-}
-
-/* needs fixing if non-identity matrix used */
static void imm_drawcone(const float vec[3], float radius, float height, float tmat[4][4], unsigned pos)
{
float cur[3];
@@ -7527,7 +7728,7 @@ static void imm_drawcone(const float vec[3], float radius, float height, float t
}
/* return true if nothing was drawn */
-static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy *base,
+static bool drawmball(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Base *base,
const char dt, const short dflag, const unsigned char ob_wire_col[4])
{
Object *ob = base->object;
@@ -7541,15 +7742,13 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy
if ((G.f & G_PICKSEL) == 0) {
unsigned char wire_col[4];
UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_col);
- glColor3ubv(wire_col);
-
- drawDispList(scene, v3d, rv3d, base, dt, dflag, wire_col);
+ drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, wire_col);
}
ml = mb->editelems->first;
}
else {
if ((base->flag_legacy & OB_FROMDUPLI) == 0) {
- drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
ml = mb->elems.first;
}
@@ -7566,20 +7765,25 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy
normalize_v3(imat[0]);
normalize_v3(imat[1]);
+#if 0 /* no purpose? */
if (mb->editelems == NULL) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
glColor3ubv(ob_wire_col);
}
}
-
+#endif
+
glLineWidth(1.0f);
+ const int unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
while (ml) {
/* draw radius */
if (mb->editelems) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) cpack(0xA0A0F0);
- else cpack(0x3030A0);
+ if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0A0F0);
+ else imm_cpack(0x3030A0);
}
if (G.f & G_PICKSEL) {
@@ -7587,24 +7791,26 @@ static bool drawmball(Scene *scene, View3D *v3d, RegionView3D *rv3d, BaseLegacy
GPU_select_load_id(code++);
}
}
- drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad, imat);
+ imm_drawcircball(&(ml->x), ml->rad, imat, pos);
/* draw stiffness */
if (mb->editelems) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) cpack(0xA0F0A0);
- else cpack(0x30A030);
+ if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) imm_cpack(0xA0F0A0);
+ else imm_cpack(0x30A030);
}
if (G.f & G_PICKSEL) {
ml->selcol2 = code;
GPU_select_load_id(code++);
}
- drawcircball(GL_LINE_LOOP, &(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat);
+ imm_drawcircball(&(ml->x), ml->rad * atanf(ml->s) / (float)M_PI_2, imat, pos);
}
ml = ml->next;
}
+
+ immUnbindProgram();
return false;
}
@@ -7614,6 +7820,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
PartDeflect *pd = ob->pd;
float imat[4][4], tmat[4][4];
float vec[3] = {0.0, 0.0, 0.0};
+ float draw_color[3] = {0.0f, 0.0f, 0.0f};
/* scale size of circle etc with the empty drawsize */
const float size = (ob->type == OB_EMPTY) ? ob->empty_drawsize : 1.0f;
@@ -7623,35 +7830,53 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
normalize_v3(imat[0]); /* we don't do this because field doesnt scale either... apart from wind! */
normalize_v3(imat[1]);
#endif
+
+ const int unsigned pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3fv(draw_color);
if (pd->forcefield == PFIELD_WIND) {
float force_val = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
unit_m4(tmat);
force_val *= 0.1f;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 0.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 1.0f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 1.5f * force_val;
- drawcircball(GL_LINE_LOOP, vec, size, tmat);
+ imm_drawcircball(vec, size, tmat, pos);
vec[2] = 0.0f; /* reset vec for max dist circle */
-
}
else if (pd->forcefield == PFIELD_FORCE) {
float ffall_val = pd->f_power;
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
- drawcircball(GL_LINE_LOOP, vec, size, imat);
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val));
- drawcircball(GL_LINE_LOOP, vec, size * 1.5f, imat);
- if ((dflag & DRAW_CONSTCOLOR) == 0) ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val));
- drawcircball(GL_LINE_LOOP, vec, size * 2.0f, imat);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size, imat, pos);
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(1.5f, ffall_val), draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size * 1.5f, imat, pos);
+
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.9f - 0.4f / powf(2.0f, ffall_val), draw_color);
+ immUniformColor3fv(draw_color);
+ }
+
+ imm_drawcircball(vec, size * 2.0f, imat, pos);
}
else if (pd->forcefield == PFIELD_VORTEX) {
float force_val = pd->f_strength;
@@ -7659,16 +7884,17 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
unit_m4(tmat);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.7f, draw_color);
+ immUniformColor3fv(draw_color);
}
if (force_val < 0) {
- drawspiral(vec, size, tmat, 1);
- drawspiral(vec, size, tmat, 16);
+ drawspiral(pos, vec, size, tmat, 1);
+ drawspiral(pos, vec, size, tmat, 16);
}
else {
- drawspiral(vec, size, tmat, -1);
- drawspiral(vec, size, tmat, -16);
+ drawspiral(pos, vec, size, tmat, -1);
+ drawspiral(pos, vec, size, tmat, -16);
}
}
else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) {
@@ -7678,18 +7904,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
float mindist = pd->f_strength;
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
/* path end */
setlinestyle(3);
where_on_path(ob, 1.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+ imm_drawcircball(guidevec1, mindist, imat, pos);
/* path beginning */
setlinestyle(0);
where_on_path(ob, 0.0f, guidevec1, guidevec2, NULL, NULL, NULL);
- drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+ imm_drawcircball(guidevec1, mindist, imat, pos);
copy_v3_v3(vec, guidevec1); /* max center */
}
@@ -7698,16 +7925,19 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
setlinestyle(3);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
- ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f);
+ ob_wire_color_blend_theme_id(ob_wire_col, TH_BACK, 0.5f, draw_color);
+ immUniformColor3fv(draw_color);
}
if (pd->falloff == PFIELD_FALL_SPHERE) {
/* as last, guide curve alters it */
- if (pd->flag & PFIELD_USEMAX)
- drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
+ if ((pd->flag & PFIELD_USEMAX) != 0) {
+ imm_drawcircball(vec, pd->maxdist, imat, pos);
+ }
- if (pd->flag & PFIELD_USEMIN)
- drawcircball(GL_LINE_LOOP, vec, pd->mindist, imat);
+ if ((pd->flag & PFIELD_USEMIN) != 0) {
+ imm_drawcircball(vec, pd->mindist, imat, pos);
+ }
}
else if (pd->falloff == PFIELD_FALL_TUBE) {
float radius, distance;
@@ -7720,16 +7950,18 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
vec[2] = distance;
distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance;
- if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR))
- drawtube(vec, radius, distance, tmat);
+ if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
+ imm_drawtube(vec, radius, distance, tmat, pos);
+ }
radius = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
vec[2] = distance;
distance = (pd->flag & PFIELD_POSZ) ? -distance : -2.0f * distance;
- if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR))
- drawtube(vec, radius, distance, tmat);
+ if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
+ imm_drawtube(vec, radius, distance, tmat, pos);
+ }
}
else if (pd->falloff == PFIELD_FALL_CONE) {
float radius, distance;
@@ -7740,38 +7972,23 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d,
distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
- drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos);
if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos);
}
radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
- drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), distance * cosf(radius), tmat, pos);
if ((pd->flag & PFIELD_POSZ) == 0)
- drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat);
+ imm_drawcone(vec, distance * sinf(radius), -distance * cosf(radius), tmat, pos);
}
}
setlinestyle(0);
-}
-static void draw_box(const float vec[8][3], bool solid)
-{
- glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vec);
-
- if (solid) {
- const GLubyte indices[24] = {0,1,2,3,7,6,5,4,4,5,1,0,3,2,6,7,3,7,4,0,1,5,6,2};
- glDrawRangeElements(GL_QUADS, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
- }
- else {
- const GLubyte indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7};
- glDrawRangeElements(GL_LINES, 0, 7, 24, GL_UNSIGNED_BYTE, indices);
- }
-
- glDisableClientState(GL_VERTEX_ARRAY);
+ immUnbindProgram();
}
static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
@@ -7798,12 +8015,12 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
immEnd();
}
-static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
+static void imm_draw_bb(BoundBox *bb, char type, bool around_origin, const unsigned char ob_wire_col[4])
{
float size[3], cent[3];
- GLUquadricObj *qobj = gluNewQuadric();
-
- gluQuadricDrawStyle(qobj, GLU_SILHOUETTE);
+ Batch *sphere = Batch_get_sphere_wire(0);
+ Batch_set_builtin_program(sphere, GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) Batch_Uniform4f(sphere, "color", ob_wire_col[0]/255.0f, ob_wire_col[1]/255.0f, ob_wire_col[2]/255.0f, 1.0f);
BKE_boundbox_calc_size_aabb(bb, size);
@@ -7814,40 +8031,51 @@ static void draw_bb_quadric(BoundBox *bb, char type, bool around_origin)
BKE_boundbox_calc_center_aabb(bb, cent);
}
- glPushMatrix();
+ gpuPushMatrix();
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
if (type == OB_BOUND_SPHERE) {
float scale = MAX3(size[0], size[1], size[2]);
- glTranslate3fv(cent);
- glScalef(scale, scale, scale);
- gluSphere(qobj, 1.0, 8, 5);
+ gpuTranslate3fv(cent);
+ gpuRotateAxis(90, 'X');
+ gpuScaleUniform(scale);
+ Batch_draw(sphere);
}
else if (type == OB_BOUND_CYLINDER) {
float radius = size[0] > size[1] ? size[0] : size[1];
- glTranslatef(cent[0], cent[1], cent[2] - size[2]);
- glScalef(radius, radius, 2.0f * size[2]);
- gluCylinder(qobj, 1.0, 1.0, 1.0, 8, 1);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
+ gpuScale3f(radius, radius, 2.0f * size[2]);
+ imm_cylinder_wire(pos, 1.0f, 1.0f, 1.0f, 8, 1);
}
else if (type == OB_BOUND_CONE) {
float radius = size[0] > size[1] ? size[0] : size[1];
- glTranslatef(cent[0], cent[1], cent[2] - size[2]);
- glScalef(radius, radius, 2.0f * size[2]);
- gluCylinder(qobj, 1.0, 0.0, 1.0, 8, 1);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - size[2]);
+ gpuScale3f(radius, radius, 2.0f * size[2]);
+ imm_cylinder_wire(pos, 1.0f, 0.0f, 1.0f, 8, 1);
+
}
else if (type == OB_BOUND_CAPSULE) {
float radius = size[0] > size[1] ? size[0] : size[1];
float length = size[2] > radius ? 2.0f * (size[2] - radius) : 0.0f;
- glTranslatef(cent[0], cent[1], cent[2] - length * 0.5f);
- gluCylinder(qobj, radius, radius, length, 8, 1);
- gluSphere(qobj, radius, 8, 4);
- glTranslatef(0.0, 0.0, length);
- gluSphere(qobj, radius, 8, 4);
+ gpuTranslate3f(cent[0], cent[1], cent[2] - length * 0.5f);
+ imm_cylinder_wire(pos, radius, radius, length, 8, 1);
+
+ gpuRotateAxis(90, 'X');
+ gpuScaleUniform(radius);
+ Batch_draw(sphere);
+
+ gpuTranslate3f(0.0f, length / radius, 0.0f);
+ Batch_draw(sphere);
}
- glPopMatrix();
-
- gluDeleteQuadric(qobj);
+
+ gpuPopMatrix();
+ immUnbindProgram();
}
-void draw_bounding_volume(Object *ob, char type)
+void draw_bounding_volume(Object *ob, char type, const unsigned char ob_wire_col[4])
{
BoundBox bb_local;
BoundBox *bb = NULL;
@@ -7877,12 +8105,16 @@ void draw_bounding_volume(Object *ob, char type)
if (bb == NULL)
return;
-
+
if (ob->gameflag & OB_BOUNDS) { /* bounds need to be drawn around origin for game engine */
if (type == OB_BOUND_BOX) {
float vec[8][3], size[3];
-
+
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
BKE_boundbox_calc_size_aabb(bb, size);
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
@@ -7892,21 +8124,31 @@ void draw_bounding_volume(Object *ob, char type)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec, false);
+ imm_draw_box(vec, false, pos);
+
+ immUnbindProgram();
}
else {
- draw_bb_quadric(bb, type, true);
+ imm_draw_bb(bb, type, true, ob_wire_col);
}
}
else {
- if (type == OB_BOUND_BOX)
- draw_box(bb->vec, false);
+ if (type == OB_BOUND_BOX) {
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
+ imm_draw_box(bb->vec, false, pos);
+
+ immUnbindProgram();
+ }
else
- draw_bb_quadric(bb, type, false);
+ imm_draw_bb(bb, type, false, ob_wire_col);
}
+
}
-static void drawtexspace(Object *ob)
+static void drawtexspace(Object *ob, const unsigned char ob_wire_col[3])
{
float vec[8][3], loc[3], size[3];
@@ -7936,14 +8178,27 @@ static void drawtexspace(Object *ob)
setlinestyle(2);
- draw_box(vec, false);
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+
+ if (ob_wire_col) {
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_3D_DEPTH_ONLY);
+ }
+
+ imm_draw_box(vec, false, pos);
+
+ immUnbindProgram();
setlinestyle(0);
}
/* draws wire outline */
-static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
- const unsigned char ob_wire_col[4])
+static void draw_object_selected_outline(
+ Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, Base *base,
+ const unsigned char ob_wire_col[4])
{
RegionView3D *rv3d = ar->regiondata;
Object *ob = base->object;
@@ -7972,11 +8227,11 @@ static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion
if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->bb)) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
if (dm) {
- draw_mesh_object_outline(v3d, ob, dm);
+ draw_mesh_object_outline(v3d, ob, dm, ob_wire_col);
}
else {
/* only draw 'solid' parts of the display list as wire. */
- drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF));
+ drawDispListwire_ex(&ob->curve_cache->disp, (DL_INDEX3 | DL_INDEX4 | DL_SURF), ob_wire_col);
}
}
}
@@ -7984,7 +8239,7 @@ static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion
if (BKE_mball_is_basis(ob)) {
if ((base->flag_legacy & OB_FROMDUPLI) == 0) {
glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
- drawDispListwire(&ob->curve_cache->disp, ob->type);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, ob_wire_col);
}
}
}
@@ -8001,13 +8256,8 @@ static void drawObjectSelect(Scene *scene, SceneLayer *sl, View3D *v3d, ARegion
static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const unsigned char ob_wire_col[4])
{
if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL)) {
-
- if (scene->obedit == ob) {
- UI_ThemeColor(TH_WIRE_EDIT);
- }
- else {
- glColor3ubv(ob_wire_col);
- }
+ unsigned char wire_edit_col[4];
+ UI_GetThemeColor4ubv(TH_WIRE_EDIT, wire_edit_col);
ED_view3d_polygon_offset(rv3d, 1.0);
glDepthMask(GL_FALSE); /* disable write in zbuffer, selected edge wires show better */
@@ -8020,13 +8270,13 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
drawCurveDMWired(ob);
}
else {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
}
}
}
else if (ob->type == OB_MBALL) {
if (BKE_mball_is_basis(ob)) {
- drawDispListwire(&ob->curve_cache->disp, ob->type);
+ drawDispListwire(&ob->curve_cache->disp, ob->type, (scene->obedit == ob) ? wire_edit_col : ob_wire_col);
}
}
@@ -8036,7 +8286,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, const
}
/* should be called in view space */
-static void draw_hooks(Object *ob)
+static void draw_hooks(Object *ob, unsigned int pos)
{
for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
if (md->type == eModifierType_Hook) {
@@ -8047,17 +8297,17 @@ static void draw_hooks(Object *ob)
if (hmd->object) {
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(hmd->object->obmat[3]);
- glVertex3fv(vec);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, hmd->object->obmat[3]);
+ immVertex3fv(pos, vec);
+ immEnd();
setlinestyle(0);
}
glPointSize(3.0f);
- glBegin(GL_POINTS);
- glVertex3fv(vec);
- glEnd();
+ immBegin(GL_POINTS, 1);
+ immVertex3fv(pos, vec);
+ immEnd();
}
}
}
@@ -8068,9 +8318,16 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
const char *axis_str[3] = {"px", "py", "pz"};
float mat[4][4];
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
eul_to_mat4(mat, &data->axX);
glLineWidth(4.0f);
setlinestyle(2);
+
+ immBegin(GL_LINES, 6);
for (int axis = 0; axis < 3; axis++) {
float dir[3] = {0, 0, 0};
float v[3];
@@ -8078,12 +8335,10 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
copy_v3_v3(v, &data->pivX);
dir[axis] = 1.0f;
- glBegin(GL_LINES);
mul_m4_v3(mat, dir);
add_v3_v3(v, dir);
- glVertex3fv(&data->pivX);
- glVertex3fv(v);
- glEnd();
+ immVertex3fv(pos, &data->pivX);
+ immVertex3fv(pos, v);
/* when const color is set wirecolor is NULL - we could get the current color but
* with selection and group instancing its not needed to draw the text */
@@ -8091,8 +8346,12 @@ static void draw_rigid_body_pivot(bRigidBodyJointConstraint *data,
view3d_cached_text_draw_add(v, axis_str[axis], 2, 0, V3D_CACHE_TEXT_ASCII, ob_wire_col);
}
}
+ immEnd();
setlinestyle(0);
+ glLineWidth(1.0f);
+
+ immUnbindProgram();
}
void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned char r_ob_wire_col[4])
@@ -8125,7 +8384,7 @@ void draw_object_wire_color(Scene *scene, SceneLayer *sl, Base *base, unsigned c
/* uses darker active color for non-active + selected */
theme_id = TH_GROUP_ACTIVE;
- if (scene->basact != base) {
+ if (sl->basact != base) {
theme_shade = -16;
}
}
@@ -8189,10 +8448,11 @@ static void draw_object_matcap_check(View3D *v3d, Object *ob)
v3d->flag2 |= V3D_SHOW_SOLID_MATCAP;
}
-void draw_rigidbody_shape(Object *ob)
+void draw_rigidbody_shape(Object *ob, const unsigned char ob_wire_col[4])
{
BoundBox *bb = NULL;
float size[3], vec[8][3];
+ unsigned int pos;
if (ob->type == OB_MESH) {
bb = BKE_mesh_boundbox_get(ob);
@@ -8205,6 +8465,10 @@ void draw_rigidbody_shape(Object *ob)
case RB_SHAPE_BOX:
BKE_boundbox_calc_size_aabb(bb, size);
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
+
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = -size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = +size[0];
vec[0][1] = vec[1][1] = vec[4][1] = vec[5][1] = -size[1];
@@ -8212,19 +8476,20 @@ void draw_rigidbody_shape(Object *ob)
vec[0][2] = vec[3][2] = vec[4][2] = vec[7][2] = -size[2];
vec[1][2] = vec[2][2] = vec[5][2] = vec[6][2] = +size[2];
- draw_box(vec, false);
+ imm_draw_box(vec, false, pos);
+ immUnbindProgram();
break;
case RB_SHAPE_SPHERE:
- draw_bb_quadric(bb, OB_BOUND_SPHERE, true);
+ imm_draw_bb(bb, OB_BOUND_SPHERE, true, ob_wire_col);
break;
case RB_SHAPE_CONE:
- draw_bb_quadric(bb, OB_BOUND_CONE, true);
+ imm_draw_bb(bb, OB_BOUND_CONE, true, ob_wire_col);
break;
case RB_SHAPE_CYLINDER:
- draw_bb_quadric(bb, OB_BOUND_CYLINDER, true);
+ imm_draw_bb(bb, OB_BOUND_CYLINDER, true, ob_wire_col);
break;
case RB_SHAPE_CAPSULE:
- draw_bb_quadric(bb, OB_BOUND_CAPSULE, true);
+ imm_draw_bb(bb, OB_BOUND_CAPSULE, true, ob_wire_col);
break;
}
}
@@ -8363,7 +8628,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
draw_object_wire_color(scene, sl, base, _ob_wire_col);
ob_wire_col = _ob_wire_col;
- glColor3ubv(ob_wire_col);
+ //glColor3ubv(ob_wire_col);
}
/* maximum drawtype */
@@ -8416,7 +8681,7 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((v3d->flag & V3D_SELECT_OUTLINE) && !render_override && ob->type != OB_MESH) {
if (dt > OB_WIRE && (ob->mode & OB_MODE_EDIT) == 0 && (dflag & DRAW_SCENESET) == 0) {
if (!(ob->dtx & OB_DRAWWIRE) && (base->flag & BASE_SELECTED) && !(dflag & (DRAW_PICKING | DRAW_CONSTCOLOR))) {
- drawObjectSelect(scene, sl, v3d, ar, base, ob_wire_col);
+ draw_object_selected_outline(scene, sl, v3d, ar, base, ob_wire_col);
}
}
}
@@ -8433,10 +8698,10 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
switch (ob->type) {
case OB_MESH:
if (IS_VIEWPORT_LEGACY(v3d)) {
- empty_object = draw_mesh_object(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ empty_object = draw_mesh_object(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
}
else {
- empty_object = draw_mesh_object_new(scene, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
+ empty_object = draw_mesh_object_new(scene, sl, ar, v3d, rv3d, base, dt, ob_wire_col, dflag);
}
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* mesh draws wire itself */
@@ -8447,18 +8712,18 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
case OB_FONT:
cu = ob->data;
if (cu->editfont) {
- draw_editfont(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ draw_editfont(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
else if (dt == OB_BOUNDBOX) {
if ((render_override && v3d->drawtype >= OB_WIRE) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
break;
@@ -8468,18 +8733,18 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if (cu->editnurb) {
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
- draw_editnurb(scene, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
+ draw_editnurb(scene, sl, v3d, rv3d, base, nurbs->first, dt, dflag, ob_wire_col);
}
else if (dt == OB_BOUNDBOX) {
if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else if (ED_view3d_boundbox_clip(rv3d, ob->bb)) {
- empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawDispList(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
}
break;
case OB_MBALL:
@@ -8487,17 +8752,17 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
MetaBall *mb = ob->data;
if (mb->editelems)
- drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ drawmball(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
else if (dt == OB_BOUNDBOX) {
if ((render_override && (v3d->drawtype >= OB_WIRE)) == 0) {
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, base->object);
#endif
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
}
else
- empty_object = drawmball(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
+ empty_object = drawmball(scene, sl, v3d, rv3d, base, dt, dflag, ob_wire_col);
break;
}
case OB_EMPTY:
@@ -8532,13 +8797,13 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((dt == OB_BOUNDBOX) && (ob->mode & OB_MODE_EDIT))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
#ifdef SEQUENCER_DAG_WORKAROUND
ensure_curve_cache(scene, ob);
#endif
- drawlattice(v3d, ob);
+ drawlattice(v3d, ob, dflag, ob_wire_col);
}
}
break;
@@ -8548,11 +8813,20 @@ void draw_object(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *b
if ((dt == OB_BOUNDBOX) && (ob->mode & (OB_MODE_EDIT | OB_MODE_POSE)))
dt = OB_WIRE;
if (dt == OB_BOUNDBOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
else {
+ unsigned char arm_col[4];
glLineWidth(1.0f);
- empty_object = draw_armature(scene, sl, v3d, ar, base, dt, dflag, ob_wire_col, false);
+
+ if (ob_wire_col == NULL) {
+ float fcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ rgba_float_to_uchar(arm_col, fcol);
+ }
+ else
+ copy_v4_v4_uchar(arm_col, ob_wire_col);
+
+ empty_object = draw_armature(scene, sl, v3d, ar, base, dt, dflag, arm_col, false);
}
}
break;
@@ -8574,12 +8848,12 @@ afterdraw:
if ((sb = ob->soft)) {
if (sb->solverflags & SBSO_ESTIMATEIPO) {
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
copy_m3_m3(msc, sb->lscale);
copy_m3_m3(mrt, sb->lrot);
mul_m3_m3m3(mtr, mrt, msc);
ob_draw_RE_motion(sb->lcom, mtr, tipw, tiph, drawsize);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix3D(ob->obmat);
}
}
}
@@ -8604,7 +8878,7 @@ afterdraw:
}
//glDepthMask(GL_FALSE);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
view3d_cached_text_draw_begin();
@@ -8613,7 +8887,7 @@ afterdraw:
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
PTCacheEdit *edit = PE_create_current(scene, ob);
if (edit && edit->psys == psys)
- draw_update_ptcache_edit(scene, ob, edit);
+ draw_update_ptcache_edit(scene, sl, ob, edit);
}
draw_new_particle_system(scene, v3d, rv3d, base, psys, dt, dflag);
@@ -8621,7 +8895,7 @@ afterdraw:
invert_m4_m4(ob->imat, ob->obmat);
view3d_cached_text_draw_end(v3d, ar, 0, NULL);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix3D(ob->obmat);
//glDepthMask(GL_TRUE);
if (col) cpack(col);
@@ -8635,10 +8909,10 @@ afterdraw:
if (ob->mode & OB_MODE_PARTICLE_EDIT && is_obact) {
PTCacheEdit *edit = PE_create_current(scene, ob);
if (edit) {
- glLoadMatrixf(rv3d->viewmat);
- draw_update_ptcache_edit(scene, ob, edit);
+ gpuLoadMatrix3D(rv3d->viewmat);
+ draw_update_ptcache_edit(scene, sl, ob, edit);
draw_ptcache_edit(scene, v3d, edit);
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix3D(ob->obmat);
}
}
}
@@ -8649,19 +8923,22 @@ afterdraw:
const bool show_smoke = (CFRA >= sds->point_cache[0]->startframe);
float viewnormal[3];
- glLoadMatrixf(rv3d->viewmat);
- glMultMatrixf(ob->obmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
+ gpuMultMatrix3D(ob->obmat);
if (!render_override) {
BoundBox bb;
float p0[3], p1[3];
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ if (ob_wire_col) immUniformColor3ubv(ob_wire_col);
/* draw max domain bounds */
if ((sds->flags & MOD_SMOKE_ADAPTIVE_DOMAIN)) {
VECSUBFAC(p0, sds->p0, sds->cell_size, sds->adapt_res);
VECADDFAC(p1, sds->p1, sds->cell_size, sds->adapt_res);
BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec, false);
+ imm_draw_box(bb.vec, false, pos);
}
/* draw a single voxel to hint the user about the resolution of the fluid */
@@ -8675,7 +8952,9 @@ afterdraw:
}
BKE_boundbox_init_from_minmax(&bb, p0, p1);
- draw_box(bb.vec, false);
+ imm_draw_box(bb.vec, false, pos);
+
+ immUnbindProgram();
}
/* don't show smoke before simulation starts, this could be made an option in the future */
@@ -8731,29 +9010,37 @@ afterdraw:
if ((ob->gameflag & OB_BOUNDS) && (ob->mode == OB_MODE_OBJECT)) {
if (ob->boundtype != ob->collision_boundtype || (dtx & OB_DRAWBOUNDOX) == 0) {
setlinestyle(2);
- draw_bounding_volume(ob, ob->collision_boundtype);
+ draw_bounding_volume(ob, ob->collision_boundtype, ob_wire_col);
setlinestyle(0);
}
}
if (ob->rigidbody_object) {
- draw_rigidbody_shape(ob);
+ draw_rigidbody_shape(ob, ob_wire_col);
}
/* draw extra: after normal draw because of makeDispList */
if (dtx && (G.f & G_RENDER_OGL) == 0) {
if (dtx & OB_AXIS) {
- drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL);
+ if ((dflag & DRAW_CONSTCOLOR) == 0) {
+ /* prevent random colors being used */
+ drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, ob_wire_col);
+ }
+ else {
+ drawaxes(rv3d->viewmatob, 1.0f, OB_ARROWS, NULL);
+ }
}
if (dtx & OB_DRAWBOUNDOX) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, ob_wire_col);
}
if (dtx & OB_TEXSPACE) {
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* prevent random colors being used */
- glColor3ubv(ob_wire_col);
+ drawtexspace(ob, ob_wire_col);
+ }
+ else {
+ drawtexspace(ob, NULL);
}
- drawtexspace(ob);
}
if (dtx & OB_DRAWNAME) {
/* patch for several 3d cards (IBM mostly) that crash on GL_SELECT with text drawing */
@@ -8780,16 +9067,21 @@ afterdraw:
{
float imat[4][4], vec[3] = {0.0f, 0.0f, 0.0f};
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
invert_m4_m4(imat, rv3d->viewmatob);
if ((dflag & DRAW_CONSTCOLOR) == 0) {
/* prevent random colors being used */
- glColor3ubv(ob_wire_col);
+ immUniformColor3ubv(ob_wire_col);
}
setlinestyle(2);
- drawcircball(GL_LINE_LOOP, vec, ob->inertia, imat);
+ imm_drawcircball(vec, ob->inertia, imat, pos);
setlinestyle(0);
+
+ immUnbindProgram();
}
}
@@ -8799,7 +9091,7 @@ afterdraw:
/* return warning, clear temp flag */
v3d->flag2 &= ~V3D_SHOW_SOLID_MATCAP;
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
if (zbufoff) {
glDisable(GL_DEPTH_TEST);
@@ -8859,17 +9151,21 @@ afterdraw:
ListBase *list;
RigidBodyCon *rbc = ob->rigidbody_constraint;
+ unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor3ubv(ob_wire_col);
+
/* draw hook center and offset line */
if (ob != scene->obedit)
- draw_hooks(ob);
+ draw_hooks(ob, pos);
/* help lines and so */
if (ob != scene->obedit && ob->parent && (ob->parent->lay & v3d->lay)) {
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(ob->orig);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, ob->orig);
+ immEnd();
setlinestyle(0);
}
@@ -8883,7 +9179,7 @@ afterdraw:
UI_GetThemeColor3ubv(TH_GRID, col1);
UI_make_axis_color(col1, col2, 'Z');
- glColor3ubv(col2);
+ immUniformColor3ubv(col2);
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
@@ -8908,10 +9204,10 @@ afterdraw:
if (camob) {
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(camob->obmat[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, camob->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
setlinestyle(0);
}
}
@@ -8932,10 +9228,10 @@ afterdraw:
unit_m4(ct->matrix);
setlinestyle(3);
- glBegin(GL_LINES);
- glVertex3fv(ct->matrix[3]);
- glVertex3fv(ob->obmat[3]);
- glEnd();
+ immBegin(GL_LINES, 2);
+ immVertex3fv(pos, ct->matrix[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immEnd();
setlinestyle(0);
}
@@ -8948,26 +9244,71 @@ afterdraw:
BKE_constraints_clear_evalob(cob);
}
/* draw rigid body constraint lines */
- if (rbc) {
- UI_ThemeColor(TH_WIRE);
+ if (rbc && (rbc->ob1 || rbc->ob2)) {
+ immUniformThemeColor(TH_WIRE);
+
setlinestyle(3);
- glBegin(GL_LINES);
+ immBegin(GL_LINES, ((int)((bool)rbc->ob1) + (int)((bool)rbc->ob2)) * 2);
if (rbc->ob1) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob1->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, rbc->ob1->obmat[3]);
}
if (rbc->ob2) {
- glVertex3fv(ob->obmat[3]);
- glVertex3fv(rbc->ob2->obmat[3]);
+ immVertex3fv(pos, ob->obmat[3]);
+ immVertex3fv(pos, rbc->ob2->obmat[3]);
}
- glEnd();
+ immEnd();
setlinestyle(0);
}
+
+ immUnbindProgram();
}
ED_view3d_clear_mats_rv3d(rv3d);
}
+
+/**
+ * Drawing for selection picking,
+ * caller must have called 'GPU_select_load_id(base->selcode)' first.
+ */
+void draw_object_select(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, Base *base, const short dflag)
+{
+ BLI_assert(dflag & DRAW_PICKING && dflag & DRAW_CONSTCOLOR);
+ draw_object(scene, sl, ar, v3d, base, dflag);
+
+ /* we draw duplicators for selection too */
+ if ((base->object->transflag & OB_DUPLI)) {
+ ListBase *lb;
+ DupliObject *dob;
+ Base tbase;
+
+ tbase.flag_legacy = OB_FROMDUPLI;
+ lb = object_duplilist(G.main->eval_ctx, scene, base->object);
+
+ for (dob = lb->first; dob; dob = dob->next) {
+ float omat[4][4];
+
+ tbase.object = dob->ob;
+ copy_m4_m4(omat, dob->ob->obmat);
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+
+ /* extra service: draw the duplicator in drawtype of parent */
+ /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
+ char dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
+ short dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
+
+ draw_object(scene, sl, ar, v3d, &tbase, dflag);
+
+ tbase.object->dt = dt;
+ tbase.object->dtx = dtx;
+
+ copy_m4_m4(dob->ob->obmat, omat);
+ }
+ free_object_duplilist(lb);
+ }
+}
+
/* ***************** BACKBUF SEL (BBS) ********* */
static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const float co[3],
@@ -8977,8 +9318,10 @@ static void bbs_obmode_mesh_verts__mapFunc(void *userData, int index, const floa
MVert *mv = &data->mvert[index];
if (!(mv->flag & ME_HIDE)) {
- GPU_select_index_set(data->offset + index);
- glVertex3fv(co);
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib3ubv(data->col, (unsigned char *)&selcol);
+ immVertex3fv(data->pos, co);
}
}
@@ -8989,10 +9332,23 @@ static void bbs_obmode_mesh_verts(Object *ob, DerivedMesh *dm, int offset)
MVert *mvert = me->mvert;
data.mvert = mvert;
data.offset = offset;
+
+ VertexFormat *format = immVertexFormat();
+
+ if (dm->getNumVerts(dm) == 0) return;
+
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data.col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, dm->getNumVerts(dm));
dm->foreachMappedVert(dm, bbs_obmode_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3],
@@ -9002,17 +9358,30 @@ static void bbs_mesh_verts__mapFunc(void *userData, int index, const float co[3]
BMVert *eve = BM_vert_at_index(data->bm, index);
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(data->offset + index);
- glVertex3fv(co);
+ int selcol;
+ GPU_select_index_get(data->offset + index, &selcol);
+ immAttrib3ubv(data->col, (unsigned char *)&selcol);
+ immVertex3fv(data->pos, co);
}
}
static void bbs_mesh_verts(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawBMOffset_userData data = {em->bm, offset};
+ drawBMOffset_userData data;
+ data.bm = em->bm;
+ data.offset = offset;
+ VertexFormat *format = immVertexFormat();
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data.col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE));
- glBegin(GL_POINTS);
+
+ immBeginAtMost(GL_POINTS, em->bm->totvert);
dm->foreachMappedVert(dm, bbs_mesh_verts__mapFunc, &data, DM_FOREACH_NOP);
- glEnd();
+ immEnd();
+
+ immUnbindProgram();
}
static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
@@ -9030,7 +9399,10 @@ static DMDrawOption bbs_mesh_wire__setDrawOptions(void *userData, int index)
}
static void bbs_mesh_wire(BMEditMesh *em, DerivedMesh *dm, int offset)
{
- drawBMOffset_userData data = {em->bm, offset};
+ drawBMOffset_userData data;
+ data.bm = em->bm;
+ data.offset = offset;
+
dm->drawMappedEdges(dm, bbs_mesh_wire__setDrawOptions, &data);
}
@@ -9064,12 +9436,14 @@ static DMDrawOption bbs_mesh_solid__setSolidDrawOptions(void *userData, int inde
static void bbs_mesh_solid__drawCenter(void *userData, int index, const float cent[3], const float UNUSED(no[3]))
{
+ drawBMOffset_userData *data = (drawBMOffset_userData *)userData;
BMFace *efa = BM_face_at_index(userData, index);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- GPU_select_index_set(index + 1);
-
- glVertex3fv(cent);
+ int selcol;
+ GPU_select_index_get(index + 1, &selcol);
+ immAttrib3ubv(data->col, (unsigned char *)&selcol);
+ immVertex3fv(data->pos, cent);
}
}
@@ -9083,11 +9457,21 @@ static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d,
dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, NULL, NULL, em->bm, DM_DRAW_SKIP_HIDDEN | DM_DRAW_SELECT_USE_EDITMODE);
if (check_ob_drawface_dot(scene, v3d, ob->dt)) {
+ drawBMOffset_userData data; /* don't use offset */
+ data.bm = em->bm;
+ VertexFormat *format = immVertexFormat();
+ data.pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ data.col = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
- glBegin(GL_POINTS);
- dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, em->bm, DM_FOREACH_NOP);
- glEnd();
+ immBeginAtMost(GL_POINTS, em->bm->totface);
+ dm->foreachMappedFaceCenter(dm, bbs_mesh_solid__drawCenter, &data, DM_FOREACH_NOP);
+ immEnd();
+
+ immUnbindProgram();
}
}
@@ -9107,7 +9491,6 @@ static DMDrawOption bbs_mesh_solid_hide__setDrawOpts(void *userData, int index)
Mesh *me = userData;
if (!(me->mpoly[index].flag & ME_HIDE)) {
- GPU_select_index_set(index + 1);
return DM_DRAW_OPTION_NORMAL;
}
else {
@@ -9132,7 +9515,6 @@ static void bbs_mesh_solid_verts(Scene *scene, Object *ob)
{
Mesh *me = ob->data;
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
- glColor3ub(0, 0, 0);
DM_update_materials(dm, ob);
@@ -9150,8 +9532,6 @@ static void bbs_mesh_solid_faces(Scene *scene, Object *ob)
DerivedMesh *dm = mesh_get_derived_final(scene, ob, scene->customdata_mask);
Mesh *me = ob->data;
- glColor3ub(0, 0, 0);
-
DM_update_materials(dm, ob);
if ((me->editflag & ME_EDIT_PAINT_FACE_SEL))
@@ -9166,7 +9546,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
{
ToolSettings *ts = scene->toolsettings;
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix3D(ob->obmat);
glClearDepth(1.0); glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
@@ -9226,7 +9606,7 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
break;
}
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
@@ -9234,8 +9614,8 @@ void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, Objec
/* assumes all matrices/etc set OK */
/* helper function for drawing object instances - meshes */
-static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d,
- Object *ob, const short dt, int outline)
+static void draw_object_mesh_instance(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d,
+ Object *ob, const short dt, int outline, const unsigned char ob_wire_col[4])
{
Mesh *me = ob->data;
DerivedMesh *dm = NULL, *edm = NULL;
@@ -9250,6 +9630,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
}
if (dt <= OB_WIRE) {
+ glColor4ubv(ob_wire_col);
if (dm)
dm->drawEdges(dm, 1, 0);
else if (edm)
@@ -9257,11 +9638,11 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
}
else {
if (outline)
- draw_mesh_object_outline(v3d, ob, dm ? dm : edm);
+ draw_mesh_object_outline(v3d, ob, dm ? dm : edm, ob_wire_col);
if (dm) {
- bool glsl = draw_glsl_material(scene, ob, v3d, dt);
- GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
+ bool glsl = draw_glsl_material(scene, sl, ob, v3d, dt);
+ GPU_begin_object_materials(v3d, rv3d, scene, sl, ob, glsl, NULL);
}
glFrontFace((ob->transflag & OB_NEG_SCALE) ? GL_CW : GL_CCW);
@@ -9280,22 +9661,24 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
if (dm) dm->release(dm);
}
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline)
+void draw_object_instance(Scene *scene, SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, Object *ob, const char dt, int outline, const float wire_col[4])
{
if (ob == NULL)
return;
+ unsigned char bcol[4];
+ rgba_float_to_uchar(bcol, wire_col);
+
switch (ob->type) {
case OB_MESH:
- draw_object_mesh_instance(scene, v3d, rv3d, ob, dt, outline);
+ draw_object_mesh_instance(scene, sl, v3d, rv3d, ob, dt, outline, bcol);
break;
case OB_EMPTY:
if (ob->empty_drawtype == OB_EMPTY_IMAGE) {
- /* CONSTCOLOR == no wire outline */
- draw_empty_image(ob, DRAW_CONSTCOLOR, NULL, v3d->multiview_eye);
+ draw_empty_image(ob, 0, bcol, v3d->multiview_eye);
}
else {
- drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, NULL); /* TODO: use proper color */
+ drawaxes(rv3d->viewmatob, ob->empty_drawsize, ob->empty_drawtype, bcol);
}
break;
}
diff --git a/source/blender/editors/space_view3d/drawsimdebug.c b/source/blender/editors/space_view3d/drawsimdebug.c
index 2baa6304cd9..5984633112d 100644
--- a/source/blender/editors/space_view3d/drawsimdebug.c
+++ b/source/blender/editors/space_view3d/drawsimdebug.c
@@ -41,17 +41,16 @@
#include "BKE_effect.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h"
-#include "BIF_gl.h"
-
static void draw_sim_debug_elements(SimDebugData *debug_data, float imat[4][4])
{
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
@@ -199,12 +198,12 @@ void draw_sim_debug_data(Scene *UNUSED(scene), View3D *v3d, ARegion *ar)
invert_m4_m4(imat, rv3d->viewmatob);
- glPushMatrix();
- glLoadMatrixf(rv3d->viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix3D(rv3d->viewmat);
view3d_cached_text_draw_begin();
draw_sim_debug_elements(_sim_debug_data, imat);
view3d_cached_text_draw_end(v3d, ar, false, NULL);
- glPopMatrix();
+ gpuPopMatrix();
}
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index debdcb58d71..3a80624acd9 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -48,7 +48,6 @@
#include "BIF_gl.h"
-#include "GPU_debug.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -737,7 +736,7 @@ static void add_streamline(float (*verts)[3], float(*colors)[3], float center[3]
copy_v3_v3(verts[(*offset)++], center);
}
-typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float*, float*, float, float, int*);
+typedef void (*vector_draw_func)(float(*)[3], float(*)[3], float *, float *, float, float, int *);
#endif /* WITH_SMOKE */
void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
@@ -774,8 +773,8 @@ void draw_smoke_velocity(SmokeDomainSettings *domain, float viewnormal[3])
float min[3] = {
domain->p0[0] - domain->cell_size[0] * domain->adapt_res,
- domain->p0[1] - domain->cell_size[1] * domain->adapt_res,
- domain->p0[2] - domain->cell_size[2] * domain->adapt_res,
+ domain->p0[1] - domain->cell_size[1] * domain->adapt_res,
+ domain->p0[2] - domain->cell_size[2] * domain->adapt_res,
};
int num_points_v[3] = {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 046aa40b85d..5d437ad7abd 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -47,6 +47,7 @@
#include "BKE_icons.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_mesh_render.h"
#include "BKE_object.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@@ -58,8 +59,7 @@
#include "GPU_framebuffer.h"
#include "GPU_material.h"
#include "GPU_viewport.h"
-
-#include "BIF_gl.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -181,8 +181,8 @@ bool ED_view3d_context_user_region(bContext *C, View3D **r_v3d, ARegion **r_ar)
View3D *v3d = (View3D *)sa->spacedata.first;
if (ar) {
- RegionView3D *rv3d = ar->regiondata;
- if (rv3d && (rv3d->viewlock & RV3D_LOCKED) == 0) {
+ RegionView3D *rv3d;
+ if ((ar->regiontype == RGN_TYPE_WINDOW) && (rv3d = ar->regiondata) && (rv3d->viewlock & RV3D_LOCKED) == 0) {
*r_v3d = v3d;
*r_ar = ar;
return true;
@@ -251,7 +251,7 @@ void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d)
/* we have to multiply instead of loading viewmatob to make
* it work with duplis using displists, otherwise it will
* override the dupli-matrix */
- glMultMatrixf(ob->obmat);
+ gpuMultMatrix3D(ob->obmat);
}
#ifdef DEBUG
@@ -890,6 +890,7 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
case ND_CONSTRAINT:
case ND_KEYS:
case ND_PARTICLE:
+ case ND_POINTCACHE:
case ND_LOD:
ED_region_tag_redraw(ar);
WM_manipulatormap_tag_refresh(mmap);
@@ -903,9 +904,18 @@ static void view3d_main_region_listener(bScreen *sc, ScrArea *sa, ARegion *ar, w
break;
case NC_GEOM:
switch (wmn->data) {
+ case ND_SELECT:
+ {
+ if (scene->obedit) {
+ Object *ob = scene->obedit;
+ if (ob->type == OB_MESH) {
+ struct Mesh *me = ob->data;
+ BKE_mesh_batch_selection_dirty(me);
+ }
+ }
+ }
case ND_DATA:
case ND_VERTEX_GROUP:
- case ND_SELECT:
WM_manipulatormap_tag_refresh(mmap);
ED_region_tag_redraw(ar);
break;
@@ -1271,21 +1281,6 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot
}
break;
}
-
- /* removed since BKE_image_user_frame_calc is now called in view3d_draw_bgpic because screen_ops doesnt call the notifier. */
-#if 0
- if (wmn->category == NC_SCENE && wmn->data == ND_FRAME) {
- View3D *v3d = area->spacedata.first;
- BGpic *bgpic = v3d->bgpicbase.first;
-
- for (; bgpic; bgpic = bgpic->next) {
- if (bgpic->ima) {
- Scene *scene = wmn->reference;
- BKE_image_user_frame_calc(&bgpic->iuser, scene->r.cfra, 0);
- }
- }
- }
-#endif
}
const char *view3d_context_dir[] = {
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index 351c7ccec15..c19fdb0d4b1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -776,8 +776,8 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
return;
}
else {
- Scene *scene = CTX_data_scene(C);
- Object *ob = scene->basact->object;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = sl->basact->object;
ED_vgroup_vert_active_mirror(ob, event - B_VGRP_PNL_EDIT_SINGLE);
DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
@@ -786,8 +786,8 @@ static void do_view3d_vgroup_buttons(bContext *C, void *UNUSED(arg), int event)
static int view3d_panel_vgroup_poll(const bContext *C, PanelType *UNUSED(pt))
{
- Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
if (ob && (BKE_object_is_in_editmode_vgroup(ob) ||
BKE_object_is_in_wpaint_select_vert(ob)))
{
@@ -805,7 +805,8 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
{
uiBlock *block = uiLayoutAbsoluteBlock(pa->layout);
Scene *scene = CTX_data_scene(C);
- Object *ob = scene->basact->object;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = sl->basact->object;
MDeformVert *dv;
@@ -814,10 +815,6 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
if (dv && dv->totweight) {
ToolSettings *ts = scene->toolsettings;
- wmOperatorType *ot_weight_set_active = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
- wmOperatorType *ot_weight_paste = WM_operatortype_find("OBJECT_OT_vertex_weight_paste", true);
- wmOperatorType *ot_weight_delete = WM_operatortype_find("OBJECT_OT_vertex_weight_delete", true);
-
wmOperatorType *ot;
PointerRNA op_ptr, tools_ptr;
PointerRNA *but_ptr;
@@ -856,7 +853,7 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
/* The Weight Group Name */
- ot = ot_weight_set_active;
+ ot = WM_operatortype_find("OBJECT_OT_vertex_weight_set_active", true);
but = uiDefButO_ptr(block, UI_BTYPE_BUT, ot, WM_OP_EXEC_DEFAULT, dg->name,
xco, yco, (x = UI_UNIT_X * 5), UI_UNIT_Y, "");
but_ptr = UI_but_operator_ptr_get(but);
@@ -882,23 +879,16 @@ static void view3d_panel_vgroup(const bContext *C, Panel *pa)
xco += x;
/* The weight group paste function */
-
- ot = ot_weight_paste;
- WM_operator_properties_create_ptr(&op_ptr, ot);
- RNA_int_set(&op_ptr, "weight_group", i);
icon = (locked) ? ICON_BLANK1 : ICON_PASTEDOWN;
- uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_paste", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_int_set(&op_ptr, "weight_group", i);
/* The weight entry delete function */
-
- ot = ot_weight_delete;
- WM_operator_properties_create_ptr(&op_ptr, ot);
- RNA_int_set(&op_ptr, "weight_group", i);
icon = (locked) ? ICON_LOCKED : ICON_X;
- uiItemFullO_ptr(row, ot, "", icon, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
+ op_ptr = uiItemFullO(row, "OBJECT_OT_vertex_weight_delete", "", icon, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
+ RNA_int_set(&op_ptr, "weight_group", i);
yco -= UI_UNIT_Y;
-
}
}
}
@@ -1106,9 +1096,9 @@ static void v3d_editmetaball_buts(uiLayout *layout, Object *ob)
static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event)
{
- Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
switch (event) {
@@ -1130,16 +1120,17 @@ static void do_view3d_region_buttons(bContext *C, void *UNUSED(index), int event
static int view3d_panel_transform_poll(const bContext *C, PanelType *UNUSED(pt))
{
- Scene *scene = CTX_data_scene(C);
- return (scene->basact != NULL);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ return (sl->basact != NULL);
}
static void view3d_panel_transform(const bContext *C, Panel *pa)
{
uiBlock *block;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
- Object *ob = scene->basact->object;
+ Object *ob = sl->basact->object;
uiLayout *col;
block = uiLayoutGetBlock(pa->layout);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 46ffde7f671..d7d57d2f25d 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -35,6 +35,7 @@
#include "BKE_camera.h"
#include "BKE_context.h"
+#include "BKE_key.h"
#include "BKE_scene.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -42,19 +43,32 @@
#include "BLF_api.h"
+#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_rect.h"
+#include "BLI_string.h"
#include "BLI_threads.h"
+#include "BLT_translation.h"
+
+#include "DNA_armature_types.h"
#include "DNA_brush_types.h"
#include "DNA_camera_types.h"
+#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
+#include "DRW_engine.h"
+
+#include "ED_keyframing.h"
+#include "ED_armature.h"
+#include "ED_keyframing.h"
+#include "ED_gpencil.h"
#include "ED_screen.h"
#include "ED_transform.h"
+#include "ED_gpencil.h"
#include "GPU_matrix.h"
#include "GPU_immediate.h"
@@ -194,11 +208,8 @@ static void view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar
ED_view3d_update_viewmat(scene, v3d, ar, viewmat, winmat);
/* set for opengl */
- /* TODO(merwin): transition to GPU_matrix API */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
static bool view3d_stereo3d_active(const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d)
@@ -299,7 +310,7 @@ static void view3d_draw_debug_store_depth(ARegion *UNUSED(ar), DrawData *draw_da
if (GPU_viewport_debug_depth_is_valid(viewport)) {
if ((GPU_viewport_debug_depth_width(viewport) != w) ||
- (GPU_viewport_debug_depth_height(viewport) != h))
+ (GPU_viewport_debug_depth_height(viewport) != h))
{
GPU_viewport_debug_depth_free(viewport);
}
@@ -335,7 +346,7 @@ static void view3d_draw_debug(const bContext *C, ARegion *ar, DrawData *draw_dat
}
if (((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_SCENE_DEPTH) != 0) ||
- ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0))
+ ((v3d->tmp_compat_flag & V3D_DEBUG_SHOW_COMBINED_DEPTH) != 0))
{
/* draw */
if (GPU_viewport_debug_depth_is_valid(draw_data->viewport)) {
@@ -578,9 +589,11 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
imm_cpack(0x4040FF);
imm_draw_line_box(pos, x3, y3, x4, y4);
}
+ immUnbindProgram();
/* safety border */
if (ca) {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
if (ca->dtx & CAM_DTX_CENTER) {
float x3, y3;
@@ -656,6 +669,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
scene->safe_areas.action_center);
}
}
+ immUnbindProgram();
if (ca->flag & CAM_SHOWSENSOR) {
/* determine sensor fit, and get sensor x/y, for auto fit we
@@ -705,7 +719,6 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
v3d->camera->id.name + 2, sizeof(v3d->camera->id.name) - 2);
}
- immUnbindProgram();
}
static void drawrenderborder(ARegion *ar, View3D *v3d)
@@ -756,11 +769,10 @@ static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
rv3d->render_engine = engine;
}
- /* background draw */
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ /* rendered draw */
+ gpuPushMatrix();
+ float original_proj[4][4];
+ gpuGetProjectionMatrix3D(original_proj);
ED_region_pixelspace(ar);
if (clip_border) {
@@ -775,8 +787,8 @@ static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
}
}
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
/* don't change depth buffer */
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT); /* is this necessary? -- merwin */
/* render result draw */
@@ -788,10 +800,8 @@ static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
glScissor(scissor[0], scissor[1], scissor[2], scissor[3]);
}
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuLoadProjectionMatrix3D(original_proj);
+ gpuPopMatrix();
return true;
}
@@ -800,9 +810,7 @@ static bool view3d_draw_render_draw(const bContext *C, Scene *scene,
static void view3d_draw_background_gradient(void)
{
- gpuMatrixBegin3D(); /* TODO: finish 2D API */
-
- glClear(GL_DEPTH_BUFFER_BIT);
+ /* TODO: finish 2D API & draw background with that */
VertexFormat *format = immVertexFormat();
unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
@@ -814,7 +822,7 @@ static void view3d_draw_background_gradient(void)
UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
- immBegin(GL_QUADS, 4);
+ immBegin(PRIM_TRIANGLE_FAN, 4);
immAttrib3ubv(color, col_lo);
immVertex2f(pos, -1.0f, -1.0f);
immVertex2f(pos, 1.0f, -1.0f);
@@ -825,19 +833,12 @@ static void view3d_draw_background_gradient(void)
immEnd();
immUnbindProgram();
-
- gpuMatrixEnd();
}
static void view3d_draw_background_none(void)
{
- if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- view3d_draw_background_gradient();
- }
- else {
- UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
+ UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
}
static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
@@ -849,9 +850,6 @@ static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D
GPU_material_bind(gpumat, 1, 1, 1.0f, false, rv3d->viewmat, rv3d->viewinv, rv3d->viewcamtexcofac, (v3d->scenelock != 0));
if (GPU_material_bound(gpumat)) {
-
- glClear(GL_DEPTH_BUFFER_BIT);
-
/* TODO viewport (dfelinto): GPU_material_bind relies on immediate mode,
* we can't get rid of the following code without a bigger refactor
* or we dropping this functionality. */
@@ -864,14 +862,12 @@ static void view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D
glEnd();
GPU_material_unbind(gpumat);
+ return;
}
- else {
- view3d_draw_background_none();
- }
- }
- else {
- view3d_draw_background_none();
}
+
+ /* if any of the above fails */
+ view3d_draw_background_none();
}
/* ******************** solid plates ***************** */
@@ -885,11 +881,8 @@ static void view3d_draw_background(const bContext *C)
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
/* Background functions do not read or write depth, but they do clear or completely
- * overwrite color buffer. It's more efficient to clear color & depth in once call, so
- * background functions do this even though they don't use depth.
+ * overwrite color buffer.
*/
switch (v3d->debug.background) {
@@ -902,7 +895,6 @@ static void view3d_draw_background(const bContext *C)
case V3D_DEBUG_BACKGROUND_NONE:
default:
view3d_draw_background_none();
- break;
}
}
@@ -954,7 +946,7 @@ static void view3d_draw_outline_plates(const bContext *UNUSED(C))
#define DEBUG_GRID 0
-static void gridline_range(double x0, double dx, double max, int* first_out, int* count_out)
+static void gridline_range(double x0, double dx, double max, int *r_first, int *r_count)
{
/* determine range of gridlines that appear in this Area -- similar calc but separate ranges for x & y
* x0 is gridline 0, the axis in screen space
@@ -964,12 +956,12 @@ static void gridline_range(double x0, double dx, double max, int* first_out, int
int last = (int)floor((max - x0) / dx);
if (first <= last) {
- *first_out = first;
- *count_out = last - first + 1;
+ *r_first = first;
+ *r_count = last - first + 1;
}
else {
- *first_out = 0;
- *count_out = 0;
+ *r_first = 0;
+ *r_count = 0;
}
#if DEBUG_GRID
@@ -1114,9 +1106,9 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
glDepthMask(GL_FALSE); /* disable write in zbuffer */
#endif
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -1196,7 +1188,7 @@ static void drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **
}
}
else {
- if (dx >(GRID_MIN_PX_D * 10.0)) { /* start blending in */
+ if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
rv3d->gridview /= sublines_fl;
dx /= sublines;
if (dx > (GRID_MIN_PX_D * 10.0)) { /* start blending in */
@@ -1290,9 +1282,9 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool wr
unsigned char col_bg[3], col_grid_emphasise[3], col_grid_light[3];
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
@@ -1378,9 +1370,9 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool wr
if (show_axis_x || show_axis_y || show_axis_z) {
/* draw axis lines -- sometimes grid floor is off, other times we still need to draw the Z axis */
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
immBegin(GL_LINES, (show_axis_x + show_axis_y + show_axis_z) * 2);
@@ -1482,10 +1474,8 @@ static void view3d_draw_grid(const bContext *C, ARegion *ar)
*(&grid_unit) = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
drawgrid(&scene->unit, ar, v3d, &grid_unit);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
else {
drawfloor(scene, v3d, &grid_unit, false);
@@ -1494,9 +1484,9 @@ static void view3d_draw_grid(const bContext *C, ARegion *ar)
glDisable(GL_DEPTH_TEST);
}
-static bool is_cursor_visible(Scene *scene)
+static bool is_cursor_visible(Scene *scene, SceneLayer *sl)
{
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
/* don't draw cursor in paint modes, but with a few exceptions */
if (ob && ob->mode & OB_MODE_ALL_PAINT) {
@@ -1508,7 +1498,7 @@ static bool is_cursor_visible(Scene *scene)
}
/* exception: object in texture paint mode, clone brush, use_clone_layer disabled */
else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
- const Paint *p = BKE_paint_get_active(scene);
+ const Paint *p = BKE_paint_get_active(scene, sl);
if (p && p->brush && p->brush->imagepaint_tool == PAINT_TOOL_CLONE) {
if ((scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE) == 0) {
@@ -1536,9 +1526,9 @@ static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
glLineWidth(1.0f);
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
- unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned int color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
@@ -1648,8 +1638,6 @@ static void draw_view_axis(RegionView3D *rv3d, rcti *rect)
BLF_color4ubv(BLF_default(), axis_col[i]);
BLF_draw_default_ascii(axis_pos[i][0] + 2, axis_pos[i][1] + 2, 0.0f, axis_text, 1);
}
-
- /* BLF_draw disabled blending for us */
}
#ifdef WITH_INPUT_NDOF
@@ -1665,8 +1653,6 @@ static void draw_rotation_guide(RegionView3D *rv3d)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glPointSize(5.0f);
- glEnable(GL_POINT_SMOOTH);
glDepthMask(GL_FALSE); /* don't overwrite zbuf */
VertexFormat *format = immVertexFormat();
@@ -1745,7 +1731,11 @@ static void draw_rotation_guide(RegionView3D *rv3d)
else
color[3] = 127; /* see-through dot */
+ immUnbindProgram();
+
/* -- draw rotation center -- */
+ immBindBuiltinProgram(GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR);
+ glPointSize(5.0f);
immBegin(GL_POINTS, 1);
immAttrib4ubv(col, color);
immVertex3fv(pos, o);
@@ -1760,7 +1750,6 @@ static void draw_rotation_guide(RegionView3D *rv3d)
#endif
glDisable(GL_BLEND);
- glDisable(GL_POINT_SMOOTH);
glDepthMask(GL_TRUE);
}
#endif /* WITH_INPUT_NDOF */
@@ -1771,10 +1760,7 @@ static void view3d_draw_non_mesh(
Scene *scene, SceneLayer *sl, Object *ob, Base *base, View3D *v3d,
RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
{
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuPushMatrix(); /* necessary? --merwin */
/* multiply view with object matrix.
* local viewmat and persmat, to calculate projections */
@@ -1787,7 +1773,7 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
case OB_SURF:
case OB_MBALL:
if (is_boundingbox) {
- draw_bounding_volume(ob, ob->boundtype);
+ draw_bounding_volume(ob, ob->boundtype, color);
}
break;
case OB_EMPTY:
@@ -1814,15 +1800,12 @@ RegionView3D *rv3d, const bool is_boundingbox, const unsigned char color[4])
}
if (ob->rigidbody_object) {
- draw_rigidbody_shape(ob);
+ draw_rigidbody_shape(ob, color);
}
- ED_view3d_clear_mats_rv3d(rv3d);
+ ED_view3d_clear_mats_rv3d(rv3d); /* no effect in release builds */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix(); /* see above */
}
/* ******************** info ***************** */
@@ -1852,6 +1835,204 @@ static void view3d_draw_grease_pencil(const bContext *UNUSED(C))
/* TODO viewport */
}
+
+/**
+* Viewport Name
+*/
+static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
+{
+ const char *name = NULL;
+
+ switch (rv3d->view) {
+ case RV3D_VIEW_FRONT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
+ else name = IFACE_("Front Persp");
+ break;
+ case RV3D_VIEW_BACK:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
+ else name = IFACE_("Back Persp");
+ break;
+ case RV3D_VIEW_TOP:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
+ else name = IFACE_("Top Persp");
+ break;
+ case RV3D_VIEW_BOTTOM:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
+ else name = IFACE_("Bottom Persp");
+ break;
+ case RV3D_VIEW_RIGHT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
+ else name = IFACE_("Right Persp");
+ break;
+ case RV3D_VIEW_LEFT:
+ if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
+ else name = IFACE_("Left Persp");
+ break;
+
+ default:
+ if (rv3d->persp == RV3D_CAMOB) {
+ if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
+ Camera *cam;
+ cam = v3d->camera->data;
+ if (cam->type == CAM_PERSP) {
+ name = IFACE_("Camera Persp");
+ }
+ else if (cam->type == CAM_ORTHO) {
+ name = IFACE_("Camera Ortho");
+ }
+ else {
+ BLI_assert(cam->type == CAM_PANO);
+ name = IFACE_("Camera Pano");
+ }
+ }
+ else {
+ name = IFACE_("Object as Camera");
+ }
+ }
+ else {
+ name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
+ }
+ }
+
+ return name;
+}
+
+static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const char *name = view3d_get_name(v3d, rv3d);
+ /* increase size for unicode languages (Chinese in utf-8...) */
+#ifdef WITH_INTERNATIONAL
+ char tmpstr[96];
+#else
+ char tmpstr[32];
+#endif
+
+ if (v3d->localvd) {
+ BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
+ name = tmpstr;
+ }
+
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+#ifdef WITH_INTERNATIONAL
+ BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#else
+ BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
+#endif
+}
+
+/**
+ * draw info beside axes in bottom left-corner:
+ * framenum, object name, bone name (if available), marker name (if available)
+ */
+
+static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
+{
+ const int cfra = CFRA;
+ const char *msg_pin = " (Pinned)";
+ const char *msg_sep = " : ";
+
+ const int font_id = BLF_default();
+
+ char info[300];
+ char *s = info;
+ short offset = 1.5f * UI_UNIT_X + rect->xmin;
+
+ s += sprintf(s, "(%d)", cfra);
+
+ /*
+ * info can contain:
+ * - a frame (7 + 2)
+ * - 3 object names (MAX_NAME)
+ * - 2 BREAD_CRUMB_SEPARATORs (6)
+ * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
+ * - a marker name (MAX_NAME + 3)
+ */
+
+ /* get name of marker on current frame (if available) */
+ const char *markern = BKE_scene_find_marker_name(scene, cfra);
+
+ /* check if there is an object */
+ if (ob) {
+ *s++ = ' ';
+ s += BLI_strcpy_rlen(s, ob->id.name + 2);
+
+ /* name(s) to display depends on type of object */
+ if (ob->type == OB_ARMATURE) {
+ bArmature *arm = ob->data;
+
+ /* show name of active bone too (if possible) */
+ if (arm->edbo) {
+ if (arm->act_edbone) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_edbone->name);
+ }
+ }
+ else if (ob->mode & OB_MODE_POSE) {
+ if (arm->act_bone) {
+
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+ else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
+ /* try to display active bone and active shapekey too (if they exist) */
+
+ if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
+ Object *armobj = BKE_object_pose_armature_get(ob);
+ if (armobj && armobj->mode & OB_MODE_POSE) {
+ bArmature *arm = armobj->data;
+ if (arm->act_bone) {
+ if (arm->act_bone->layer & arm->layer) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, arm->act_bone->name);
+ }
+ }
+ }
+ }
+
+ Key *key = BKE_key_from_object(ob);
+ if (key) {
+ KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
+ if (kb) {
+ s += BLI_strcpy_rlen(s, msg_sep);
+ s += BLI_strcpy_rlen(s, kb->name);
+ if (ob->shapeflag & OB_SHAPE_LOCK) {
+ s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
+ }
+ }
+ }
+ }
+
+ /* color depends on whether there is a keyframe */
+ if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
+ UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
+ else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ else
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ }
+ else {
+ /* no object */
+ if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
+ UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
+ else
+ UI_FontThemeColor(font_id, TH_TEXT_HI);
+ }
+
+ if (markern) {
+ s += sprintf(s, " <%s>", markern);
+ }
+
+ if (U.uiflag & USER_SHOW_ROTVIEWICON)
+ offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
+
+ BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
+}
+
/* ******************** view loop ***************** */
/**
@@ -1934,17 +2115,17 @@ static void view3d_draw_solid_plates(const bContext *C, ARegion *ar, DrawData *d
{
/* realtime plates */
if ((!draw_data->is_render) || draw_data->clip_border) {
- view3d_draw_background(C);
view3d_draw_render_solid_surfaces(C, ar, true);
view3d_draw_render_transparent_surfaces(C);
view3d_draw_post_draw(C);
}
- /* offline plates*/
+ /* offline plates */
if (draw_data->is_render) {
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
+ /* TODO: move this outside of solid plates, after solid & before other 3D elements */
view3d_draw_render_draw(C, scene, ar, v3d, draw_data->clip_border, &draw_data->border_rect);
}
@@ -1978,7 +2159,6 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
((v3d->drawtype == OB_RENDER) && (v3d->prev_drawtype == OB_BOUNDBOX)));
glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
/* TODO Viewport
* we are already temporarily writing to zbuffer in draw_object()
* for now let's avoid writing again to zbuffer to prevent glitches
@@ -1994,7 +2174,6 @@ static void view3d_draw_non_meshes(const bContext *C, ARegion *ar)
}
}
- glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
}
@@ -2046,8 +2225,13 @@ static void view3d_draw_manipulators(const bContext *C, const ARegion *ar)
/**
* Information drawn on top of the solid plates and composed data
*/
-static void view3d_draw_region_info(const bContext *C, ARegion *ar)
+void view3d_draw_region_info(const bContext *C, ARegion *ar)
{
+ RegionView3D *rv3d = ar->regiondata;
+ View3D *v3d = CTX_wm_view3d(C);
+ Scene *scene = CTX_data_scene(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+
/* correct projection matrix */
ED_region_pixelspace(ar);
@@ -2058,20 +2242,36 @@ static void view3d_draw_region_info(const bContext *C, ARegion *ar)
view3d_draw_border(C, ar);
view3d_draw_grease_pencil(C);
- Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = ar->regiondata;
+ if (U.uiflag & USER_SHOW_ROTVIEWICON) {
+ draw_view_axis(rv3d, &rect);
+ }
- /* 3D cursor */
- if (is_cursor_visible(scene)) {
- drawcursor(scene, ar, v3d);
+ if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) {
+ ED_scene_draw_fps(scene, &rect);
+ }
+ else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
+ draw_viewport_name(ar, v3d, &rect);
}
- if (U.uiflag & USER_SHOW_ROTVIEWICON) {
- draw_view_axis(rv3d, &rect);
+ if (U.uiflag & USER_DRAWVIEWINFO) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
+ draw_selected_name(scene, ob, &rect);
}
+#if 0 /* TODO */
+ if (grid_unit) { /* draw below the viewport name */
+ char numstr[32] = "";
- /* TODO viewport */
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
+
+ BLF_draw_default_ascii(rect.xmin + U.widget_unit,
+ rect.ymax - (USER_SHOW_VIEWPORTNAME ? 2 * U.widget_unit : U.widget_unit), 0.0f,
+ numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
+#endif
}
/**
@@ -2086,9 +2286,27 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data
/* TODO - Technically this should be drawn to a few FBO, so we can handle
* compositing better, but for now this will get the ball rolling (dfelinto) */
+ glDepthMask(GL_TRUE); /* should be set by default */
+ glClear(GL_DEPTH_BUFFER_BIT);
+// glDisable(GL_DEPTH_TEST); /* should be set by default */
+
+ gpuMatrixBegin3D();
+
+ view3d_draw_background(C); /* clears/overwrites entire color buffer */
+
view3d_draw_setup_view(C, ar);
- view3d_draw_prerender_buffers(C, ar, draw_data);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ view3d_draw_prerender_buffers(C, ar, draw_data); /* depth pre-pass */
+
+// glDepthFunc(GL_EQUAL); /* TODO: do this after separating surfaces from wires */
+// glDepthMask(GL_FALSE); /* same TODO as above */
view3d_draw_solid_plates(C, ar, draw_data);
+
+// glDepthFunc(GL_LEQUAL); /* same TODO as above */
+// glDepthMask(GL_TRUE); /* same TODO as above */
+
view3d_draw_geometry_overlay(C);
view3d_draw_non_meshes(C, ar);
view3d_draw_other_elements(C, ar);
@@ -2097,38 +2315,25 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data
view3d_draw_manipulators(C, ar);
view3d_draw_region_info(C, ar);
+ gpuMatrixEnd();
+
+ glDisable(GL_DEPTH_TEST);
+
+ view3d_draw_region_info(C, ar);
+
#if VIEW3D_DRAW_DEBUG
view3d_draw_debug(C, ar, draw_data);
#endif
}
-static void view3d_render_pass(const bContext *C, ARegion *UNUSED(ar))
-{
- Scene *scene = CTX_data_scene(C);
- RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */
-
- if (type->flag & RE_USE_OGL_PIPELINE) {
- type->view_draw(NULL, C);
- }
- else {
- // Offline Render engine
- }
-}
-
static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data))
{
-
view3d_draw_setup_view(C, ar);
/* Only 100% compliant on new spec goes bellow */
- view3d_render_pass(C, ar);
-
- view3d_draw_grid(C, ar);
- view3d_draw_manipulators(C, ar);
- view3d_draw_region_info(C, ar);
+ DRW_draw_view(C);
}
-
void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
@@ -2145,14 +2350,14 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
if (!rv3d->viewport)
rv3d->viewport = GPU_viewport_create();
- GPU_viewport_bind(rv3d->viewport, &ar->winrct, scene->r.engine);
-
/* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
* before we even call the drawing routine, but let's move on for now (dfelinto)
* but this is a provisory way to start seeing things in the viewport */
DrawData draw_data;
view3d_draw_data_init(C, ar, rv3d, &draw_data);
+ GPU_viewport_bind(rv3d->viewport, &ar->winrct);
+
if (type->flag & RE_USE_OGL_PIPELINE)
view3d_draw_view_new(C, ar, &draw_data);
else
@@ -2169,9 +2374,9 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
* meanwhile it should keep the old viewport working.
*/
-void VP_legacy_drawcursor(Scene *scene, ARegion *ar, View3D *v3d)
+void VP_legacy_drawcursor(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d)
{
- if (is_cursor_visible(scene)) {
+ if (is_cursor_visible(scene, sl)) {
drawcursor(scene, ar, v3d);
}
}
@@ -2181,6 +2386,16 @@ void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect)
draw_view_axis(rv3d, rect);
}
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
+{
+ draw_viewport_name(ar, v3d, rect);
+}
+
+void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect)
+{
+ draw_selected_name(scene, ob, rect);
+}
+
void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit)
{
drawgrid(unit, ar, v3d, grid_unit);
@@ -2223,7 +2438,12 @@ void VP_drawrenderborder(ARegion *ar, View3D *v3d)
void VP_view3d_draw_background_none(void)
{
- view3d_draw_background_none();
+ if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+ view3d_draw_background_gradient();
+ }
+ else {
+ view3d_draw_background_none();
+ }
}
void VP_view3d_draw_background_world(Scene *scene, View3D *v3d, RegionView3D *rv3d)
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 26756a5e410..780da2de844 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -24,7 +24,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file blender/editors/space_view3d/view3d_draw.c
+/** \file blender/editors/space_view3d/view3d_draw_legacy.c
* \ingroup spview3d
*/
@@ -76,7 +76,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "WM_api.h"
@@ -99,10 +98,13 @@
#include "GPU_draw.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_compositing.h"
#include "GPU_extensions.h"
#include "GPU_immediate.h"
+#include "GPU_select.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h" /* own include */
@@ -110,19 +112,6 @@
static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *ar,
float winmat[4][4], const char *viewname);
-void circ(float x, float y, float rad)
-{
- glBegin(GL_LINE_LOOP);
- const int segments = 32;
- for (int i = 0; i < segments; ++i) {
- float angle = 2 * M_PI * ((float)i / (float)segments);
- glVertex2f(x + rad * cosf(angle),
- y + rad * sinf(angle));
- }
- glEnd();
-}
-
-
/* ********* custom clipping *********** */
static void view3d_draw_clipping(RegionView3D *rv3d)
@@ -219,199 +208,6 @@ static void draw_view_icon(RegionView3D *rv3d, rcti *rect)
glDisable(GL_BLEND);
}
-static const char *view3d_get_name(View3D *v3d, RegionView3D *rv3d)
-{
- const char *name = NULL;
-
- switch (rv3d->view) {
- case RV3D_VIEW_FRONT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Front Ortho");
- else name = IFACE_("Front Persp");
- break;
- case RV3D_VIEW_BACK:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Back Ortho");
- else name = IFACE_("Back Persp");
- break;
- case RV3D_VIEW_TOP:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Top Ortho");
- else name = IFACE_("Top Persp");
- break;
- case RV3D_VIEW_BOTTOM:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Bottom Ortho");
- else name = IFACE_("Bottom Persp");
- break;
- case RV3D_VIEW_RIGHT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Right Ortho");
- else name = IFACE_("Right Persp");
- break;
- case RV3D_VIEW_LEFT:
- if (rv3d->persp == RV3D_ORTHO) name = IFACE_("Left Ortho");
- else name = IFACE_("Left Persp");
- break;
-
- default:
- if (rv3d->persp == RV3D_CAMOB) {
- if ((v3d->camera) && (v3d->camera->type == OB_CAMERA)) {
- Camera *cam;
- cam = v3d->camera->data;
- if (cam->type == CAM_PERSP) {
- name = IFACE_("Camera Persp");
- }
- else if (cam->type == CAM_ORTHO) {
- name = IFACE_("Camera Ortho");
- }
- else {
- BLI_assert(cam->type == CAM_PANO);
- name = IFACE_("Camera Pano");
- }
- }
- else {
- name = IFACE_("Object as Camera");
- }
- }
- else {
- name = (rv3d->persp == RV3D_ORTHO) ? IFACE_("User Ortho") : IFACE_("User Persp");
- }
- }
-
- return name;
-}
-
-static void draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect)
-{
- RegionView3D *rv3d = ar->regiondata;
- const char *name = view3d_get_name(v3d, rv3d);
- /* increase size for unicode languages (Chinese in utf-8...) */
-#ifdef WITH_INTERNATIONAL
- char tmpstr[96];
-#else
- char tmpstr[32];
-#endif
-
- if (v3d->localvd) {
- BLI_snprintf(tmpstr, sizeof(tmpstr), IFACE_("%s (Local)"), name);
- name = tmpstr;
- }
-
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
-#ifdef WITH_INTERNATIONAL
- BLF_draw_default(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#else
- BLF_draw_default_ascii(U.widget_unit + rect->xmin, rect->ymax - U.widget_unit, 0.0f, name, sizeof(tmpstr));
-#endif
-}
-
-/* draw info beside axes in bottom left-corner:
- * framenum, object name, bone name (if available), marker name (if available)
- */
-
-static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
-{
- const int cfra = CFRA;
- const char *msg_pin = " (Pinned)";
- const char *msg_sep = " : ";
-
- const int font_id = BLF_default();
-
- char info[300];
- char *s = info;
- short offset = 1.5f * UI_UNIT_X + rect->xmin;
-
- s += sprintf(s, "(%d)", cfra);
-
- /*
- * info can contain:
- * - a frame (7 + 2)
- * - 3 object names (MAX_NAME)
- * - 2 BREAD_CRUMB_SEPARATORs (6)
- * - a SHAPE_KEY_PINNED marker and a trailing '\0' (9+1) - translated, so give some room!
- * - a marker name (MAX_NAME + 3)
- */
-
- /* get name of marker on current frame (if available) */
- const char *markern = BKE_scene_find_marker_name(scene, cfra);
-
- /* check if there is an object */
- if (ob) {
- *s++ = ' ';
- s += BLI_strcpy_rlen(s, ob->id.name + 2);
-
- /* name(s) to display depends on type of object */
- if (ob->type == OB_ARMATURE) {
- bArmature *arm = ob->data;
-
- /* show name of active bone too (if possible) */
- if (arm->edbo) {
- if (arm->act_edbone) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_edbone->name);
- }
- }
- else if (ob->mode & OB_MODE_POSE) {
- if (arm->act_bone) {
-
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
- else if (ELEM(ob->type, OB_MESH, OB_LATTICE, OB_CURVE)) {
- /* try to display active bone and active shapekey too (if they exist) */
-
- if (ob->type == OB_MESH && ob->mode & OB_MODE_WEIGHT_PAINT) {
- Object *armobj = BKE_object_pose_armature_get(ob);
- if (armobj && armobj->mode & OB_MODE_POSE) {
- bArmature *arm = armobj->data;
- if (arm->act_bone) {
- if (arm->act_bone->layer & arm->layer) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, arm->act_bone->name);
- }
- }
- }
- }
-
- Key *key = BKE_key_from_object(ob);
- if (key) {
- KeyBlock *kb = BLI_findlink(&key->block, ob->shapenr - 1);
- if (kb) {
- s += BLI_strcpy_rlen(s, msg_sep);
- s += BLI_strcpy_rlen(s, kb->name);
- if (ob->shapeflag & OB_SHAPE_LOCK) {
- s += BLI_strcpy_rlen(s, IFACE_(msg_pin));
- }
- }
- }
- }
-
- /* color depends on whether there is a keyframe */
- if (id_frame_has_keyframe((ID *)ob, /* BKE_scene_frame_get(scene) */ (float)cfra, ANIMFILTER_KEYS_LOCAL))
- UI_FontThemeColor(font_id, TH_TIME_KEYFRAME);
- else if (ED_gpencil_has_keyframe_v3d(scene, ob, cfra))
- UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
- else
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- }
- else {
- /* no object */
- if (ED_gpencil_has_keyframe_v3d(scene, NULL, cfra))
- UI_FontThemeColor(font_id, TH_TIME_GP_KEYFRAME);
- else
- UI_FontThemeColor(font_id, TH_TEXT_HI);
- }
-
- if (markern) {
- s += sprintf(s, " <%s>", markern);
- }
-
- if (U.uiflag & USER_SHOW_ROTVIEWICON)
- offset = U.widget_unit + (U.rvisize * 2) + rect->xmin;
-
- BLF_draw_default(offset, 0.5f * U.widget_unit, 0.0f, info, sizeof(info));
-}
-
/* *********************** backdraw for selection *************** */
static void backdrawview3d(Scene *scene, SceneLayer *sl, wmWindow *win, ARegion *ar, View3D *v3d)
@@ -958,13 +754,13 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
- glPushMatrix();
+ gpuPushMatrix();
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
+ gpuPushMatrix();
ED_region_pixelspace(ar);
- glTranslatef(centx, centy, 0.0);
- glRotatef(RAD2DEGF(-bgpic->rotation), 0.0f, 0.0f, 1.0f);
+ gpuTranslate2f(centx, centy);
+ gpuRotate2D(RAD2DEGF(-bgpic->rotation));
if (bgpic->flag & V3D_BGPIC_FLIP_X) {
zoomx *= -1.0f;
@@ -974,22 +770,16 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
zoomy *= -1.0f;
y1 = y2;
}
- glPixelZoom(zoomx, zoomy);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
- /* could not use glaDrawPixelsAuto because it could fallback to
- * glaDrawPixelsSafe in some cases, which will end up in missing
- * alpha transparency for the background image (sergey)
- */
- glaDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
-
- glPixelZoom(1.0, 1.0);
- glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend};
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTex(x1 - centx, y1 - centy, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect,
+ zoomx, zoomy, col);
glMatrixMode(GL_PROJECTION);
- glPopMatrix();
+ gpuPopMatrix();
glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
+ gpuPopMatrix();
glDisable(GL_BLEND);
@@ -1106,6 +896,35 @@ static void view3d_draw_xraytransp(Scene *scene, SceneLayer *sl, ARegion *ar, Vi
glDepthMask(GL_TRUE);
}
+/* clears zbuffer and draws it over,
+ * note that in the select version we don't care about transparent flag as with regular drawing */
+static void view3d_draw_xray_select(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, bool *clear)
+{
+ /* Not ideal, but we need to read from the previous depths before clearing
+ * otherwise we could have a function to load the depths after drawing.
+ *
+ * Clearing the depth buffer isn't all that common between drawing objects so accept this for now.
+ */
+ if (U.gpu_select_pick_deph) {
+ GPU_select_load_id(-1);
+ }
+
+ View3DAfter *v3da;
+ if (*clear && v3d->zbuf) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ *clear = false;
+ }
+
+ v3d->xray = true;
+ while ((v3da = BLI_pophead(&v3d->afterdraw_xray))) {
+ if (GPU_select_load_id(v3da->base->selcol)) {
+ draw_object_select(scene, sl, ar, v3d, v3da->base, v3da->dflag);
+ }
+ MEM_freeN(v3da);
+ }
+ v3d->xray = false;
+}
+
/* *********************** */
/*
@@ -1143,11 +962,9 @@ static void draw_dupli_objects_color(
LodLevel *savedlod;
Base tbase = {NULL};
BoundBox bb, *bb_tmp; /* use a copy because draw_object, calls clear_mesh_caches */
- GLuint displist = 0;
unsigned char color_rgb[3];
const short dflag_dupli = dflag | DRAW_CONSTCOLOR;
short transflag;
- bool use_displist = false; /* -1 is initialize */
char dt;
short dtx;
DupliApplyData *apply_data;
@@ -1169,11 +986,11 @@ static void draw_dupli_objects_color(
apply_data = duplilist_apply(base->object, scene, lb);
- DupliObject *dob_prev = NULL, *dob_next = NULL;
+ DupliObject *dob_next = NULL;
DupliObject *dob = dupli_step(lb->first);
if (dob) dob_next = dupli_step(dob->next);
- for (; dob; dob_prev = dob, dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
+ for (; dob; dob = dob_next, dob_next = dob_next ? dupli_step(dob_next->next) : NULL) {
bool testbb = false;
tbase.object = dob->ob;
@@ -1212,71 +1029,16 @@ static void draw_dupli_objects_color(
glColor3ubv(color_rgb);
}
- /* generate displist, test for new object */
- if (dob_prev && dob_prev->ob != dob->ob) {
- if (use_displist == true)
- glDeleteLists(displist, 1);
-
- use_displist = false;
- }
-
if ((bb_tmp = BKE_object_boundbox_get(dob->ob))) {
bb = *bb_tmp; /* must make a copy */
testbb = true;
}
if (!testbb || ED_view3d_boundbox_clip_ex(rv3d, &bb, dob->mat)) {
- /* generate displist */
- if (use_displist == false) {
-
- /* note, since this was added, its checked (dob->type == OB_DUPLIGROUP)
- * however this is very slow, it was probably needed for the NLA
- * offset feature (used in group-duplicate.blend but no longer works in 2.5)
- * so for now it should be ok to - campbell */
-
- if ( /* if this is the last no need to make a displist */
- (dob_next == NULL || dob_next->ob != dob->ob) ||
- /* lamp drawing messes with matrices, could be handled smarter... but this works */
- (dob->ob->type == OB_LAMP) ||
- (dob->type == OB_DUPLIGROUP && dob->animated) ||
- !bb_tmp ||
- draw_glsl_material(scene, dob->ob, v3d, dt) ||
- check_object_draw_texture(scene, v3d, dt) ||
- (v3d->flag2 & V3D_SOLID_MATCAP) != 0)
- {
- // printf("draw_dupli_objects_color: skipping displist for %s\n", dob->ob->id.name + 2);
- use_displist = false;
- }
- else {
- // printf("draw_dupli_objects_color: using displist for %s\n", dob->ob->id.name + 2);
-
- /* disable boundbox check for list creation */
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1);
- /* need this for next part of code */
- unit_m4(dob->ob->obmat); /* obmat gets restored */
-
- displist = glGenLists(1);
- glNewList(displist, GL_COMPILE);
- draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
- glEndList();
-
- use_displist = true;
- BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0);
- }
- }
-
- if (use_displist) {
- glPushMatrix();
- glMultMatrixf(dob->mat);
- glCallList(displist);
- glPopMatrix();
- }
- else {
- copy_m4_m4(dob->ob->obmat, dob->mat);
- GPU_begin_dupli_object(dob);
- draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
- GPU_end_dupli_object();
- }
+ copy_m4_m4(dob->ob->obmat, dob->mat);
+ GPU_begin_dupli_object(dob);
+ draw_object(scene, sl, ar, v3d, &tbase, dflag_dupli);
+ GPU_end_dupli_object();
}
tbase.object->dt = dt;
@@ -1291,9 +1053,6 @@ static void draw_dupli_objects_color(
}
free_object_duplilist(lb);
-
- if (use_displist)
- glDeleteLists(displist, 1);
}
void draw_dupli_objects(Scene *scene, SceneLayer *sl, ARegion *ar, View3D *v3d, BaseLegacy *base)
@@ -1421,7 +1180,7 @@ float view3d_depth_near(ViewDepths *d)
void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
{
- short zbuf = v3d->zbuf;
+ bool zbuf = v3d->zbuf;
RegionView3D *rv3d = ar->regiondata;
view3d_winmatrix_set(ar, v3d, NULL);
@@ -1433,7 +1192,7 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
glClear(GL_DEPTH_BUFFER_BIT);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
v3d->zbuf = true;
glEnable(GL_DEPTH_TEST);
@@ -1441,8 +1200,9 @@ void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d)
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
ED_gpencil_draw_view3d(NULL, scene, v3d, ar, true);
}
-
+
v3d->zbuf = zbuf;
+ if (!zbuf) glDisable(GL_DEPTH_TEST);
}
void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaoverride)
@@ -1453,8 +1213,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
short flag = v3d->flag;
float glalphaclip = U.glalphaclip;
int obcenter_dia = U.obcenter_dia;
- TODO_LAYER_CONTEXT; /* we should pass context, really */
- SceneLayer *sl = BKE_scene_layer_active(scene);
+ SceneLayer *sl = BKE_scene_layer_context_active(scene);
/* no need for color when drawing depth buffer */
const short dflag_depth = DRAW_CONSTCOLOR;
/* temp set drawtype to solid */
@@ -1472,7 +1231,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
glClear(GL_DEPTH_BUFFER_BIT);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
if (rv3d->rflag & RV3D_CLIPPING) {
ED_view3d_clipping_set(rv3d);
@@ -1487,7 +1246,7 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
if (scene->set) {
Scene *sce_iter;
for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
draw_object(scene, sl, ar, v3d, base, 0);
if (base->object->transflag & OB_DUPLI) {
draw_dupli_objects_color(scene, sl, ar, v3d, base, dflag_depth, TH_UNDEFINED);
@@ -1570,6 +1329,57 @@ void ED_view3d_draw_depth(Scene *scene, ARegion *ar, View3D *v3d, bool alphaover
U.obcenter_dia = obcenter_dia;
}
+void ED_view3d_draw_select_loop(
+ ViewContext *vc, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar,
+ bool use_obedit_skip, bool use_nearest)
+{
+ short code = 1;
+ const short dflag = DRAW_PICKING | DRAW_CONSTCOLOR;
+
+ if (vc->obedit && vc->obedit->type == OB_MBALL) {
+ draw_object(scene, sl, ar, v3d, BASACT_NEW, dflag);
+ }
+ else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
+ /* if not drawing sketch, draw bones */
+ if (!BDR_drawSketchNames(vc)) {
+ draw_object(scene, sl, ar, v3d, BASACT_NEW, dflag);
+ }
+ }
+ else {
+ Base *base;
+
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ if (((base->flag & BASE_SELECTABLED) == 0) ||
+ (use_obedit_skip && (scene->obedit->data == base->object->data)))
+ {
+ base->selcol = 0;
+ }
+ else {
+ base->selcol = code;
+
+ if (use_nearest && (base->object->dtx & OB_DRAWXRAY)) {
+ ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag);
+ }
+ else {
+ if (GPU_select_load_id(code)) {
+ draw_object(scene, sl, ar, v3d, base, dflag);
+ }
+ }
+ code++;
+ }
+ }
+ }
+
+ if (use_nearest) {
+ bool xrayclear = true;
+ if (v3d->afterdraw_xray.first) {
+ view3d_draw_xray_select(scene, sl, ar, v3d, &xrayclear);
+ }
+ }
+ }
+}
+
typedef struct View3DShadow {
struct View3DShadow *next, *prev;
GPULamp *lamp;
@@ -1608,7 +1418,7 @@ static void gpu_update_lamps_shadows_world(Scene *scene, View3D *v3d)
{
ListBase shadows;
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
World *world = scene->world;
SceneRenderLayer *srl = v3d->scenelock ? BLI_findlink(&scene->r.layers, scene->r.actlay) : NULL;
@@ -1742,9 +1552,9 @@ static void view3d_draw_objects(
const char **grid_unit,
const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
{
- SceneLayer *sl = C ? CTX_data_scene_layer(C) : BKE_scene_layer_active(scene);
+ SceneLayer *sl = C ? CTX_data_scene_layer(C) : BKE_scene_layer_render_active(scene);
RegionView3D *rv3d = ar->regiondata;
- BaseLegacy *base;
+ Base *base;
const bool do_camera_frame = !draw_offscreen;
const bool draw_grids = !draw_offscreen && (v3d->flag2 & V3D_RENDER_OVERRIDE) == 0;
const bool draw_floor = (rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO);
@@ -1777,11 +1587,8 @@ static void view3d_draw_objects(
ED_region_pixelspace(ar);
*grid_unit = NULL; /* drawgrid need this to detect/affect smallest valid unit... */
VP_legacy_drawgrid(&scene->unit, ar, v3d, grid_unit);
- /* XXX make function? replaces persp(1) */
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
else if (!draw_grids_after) {
VP_legacy_drawfloor(scene, v3d, grid_unit, true);
@@ -1802,7 +1609,7 @@ static void view3d_draw_objects(
const short dflag = DRAW_CONSTCOLOR | DRAW_SCENESET;
Scene *sce_iter;
for (SETLOOPER(scene->set, sce_iter, base)) {
- if (v3d->lay & base->lay) {
+ if ((base->flag & BASE_VISIBLED) != 0) {
UI_ThemeColorBlend(TH_WIRE, TH_BACK, 0.6f);
draw_object(scene, sl, ar, v3d, base, dflag);
@@ -1929,7 +1736,7 @@ struct RV3DMatrixStore {
float pixsize;
};
-void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
+struct RV3DMatrixStore *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
{
struct RV3DMatrixStore *rv3dmat = MEM_mallocN(sizeof(*rv3dmat), __func__);
copy_m4_m4(rv3dmat->winmat, rv3d->winmat);
@@ -1942,7 +1749,7 @@ void *ED_view3d_mats_rv3d_backup(struct RegionView3D *rv3d)
return (void *)rv3dmat;
}
-void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt)
+void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, struct RV3DMatrixStore *rv3dmat_pt)
{
struct RV3DMatrixStore *rv3dmat = rv3dmat_pt;
copy_m4_m4(rv3d->winmat, rv3dmat->winmat);
@@ -1954,10 +1761,10 @@ void ED_view3d_mats_rv3d_restore(struct RegionView3D *rv3d, void *rv3dmat_pt)
rv3d->pixsize = rv3dmat->pixsize;
}
-void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
+void ED_view3d_draw_offscreen_init(Scene *scene, SceneLayer *sl, View3D *v3d)
{
/* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
+ if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype))
gpu_update_lamps_shadows_world(scene, v3d);
}
@@ -1966,6 +1773,8 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d)
*/
static void view3d_main_region_clear(Scene *scene, View3D *v3d, ARegion *ar)
{
+ glClear(GL_DEPTH_BUFFER_BIT);
+
if (scene->world && (v3d->flag3 & V3D_SHOW_WORLD)) {
VP_view3d_draw_background_world(scene, v3d, ar->regiondata);
}
@@ -1987,8 +1796,6 @@ void ED_view3d_draw_offscreen(
bool do_compositing = false;
RegionView3D *rv3d = ar->regiondata;
- glPushMatrix();
-
/* set temporary new size */
int bwinx = ar->winx;
int bwiny = ar->winy;
@@ -2014,7 +1821,22 @@ void ED_view3d_draw_offscreen(
GPU_free_images_anim();
}
- /* setup view matrices before fx or unbinding the offscreen buffers will cause issues */
+ glMatrixMode(GL_PROJECTION);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
+ /* clear opengl buffers */
+ if (do_sky) {
+ view3d_main_region_clear(scene, v3d, ar);
+ }
+ else {
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
if ((viewname != NULL && viewname[0] != '\0') && (viewmat == NULL) && rv3d->persp == RV3D_CAMOB && v3d->camera)
view3d_stereo3d_setup_offscreen(scene, v3d, ar, winmat, viewname);
else
@@ -2035,15 +1857,6 @@ void ED_view3d_draw_offscreen(
v3d->fx_settings.ssao = ssao;
}
- /* clear opengl buffers */
- if (do_sky) {
- view3d_main_region_clear(scene, v3d, ar);
- }
- else {
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- }
-
/* main drawing call */
view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true, do_compositing ? fx : NULL);
@@ -2058,7 +1871,6 @@ void ED_view3d_draw_offscreen(
/* draw grease-pencil stuff */
ED_region_pixelspace(ar);
-
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
/* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
ED_gpencil_draw_view3d(NULL, scene, v3d, ar, false);
@@ -2073,7 +1885,10 @@ void ED_view3d_draw_offscreen(
ar->winy = bwiny;
ar->winrct = brect;
- glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ gpuPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPopMatrix();
UI_Theme_Restore(&theme_state);
@@ -2087,7 +1902,7 @@ void ED_view3d_draw_offscreen(
* (avoids re-creating when doing multiple GL renders).
*/
ImBuf *ED_view3d_draw_offscreen_imbuf(
- Scene *scene, View3D *v3d, ARegion *ar, int sizex, int sizey,
+ Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, int sizex, int sizey,
unsigned int flag, bool draw_background,
int alpha_mode, int samples, bool full_samples, const char *viewname,
/* output vars */
@@ -2116,7 +1931,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
}
}
- ED_view3d_draw_offscreen_init(scene, v3d);
+ ED_view3d_draw_offscreen_init(scene, sl, v3d);
GPU_offscreen_bind(ofs, true);
@@ -2252,7 +2067,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* \note used by the sequencer
*/
ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
- Scene *scene, Object *camera, int width, int height,
+ Scene *scene, SceneLayer *sl, Object *camera, int width, int height,
unsigned int flag, int drawtype, bool use_solid_tex, bool use_gpencil, bool draw_background,
int alpha_mode, int samples, bool full_samples, const char *viewname,
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
@@ -2306,7 +2121,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(
invert_m4_m4(rv3d.persinv, rv3d.viewinv);
return ED_view3d_draw_offscreen_imbuf(
- scene, &v3d, &ar, width, height, flag,
+ scene, sl, &v3d, &ar, width, height, flag,
draw_background, alpha_mode, samples, full_samples, viewname,
fx, ofs, err_out);
}
@@ -2473,7 +2288,7 @@ static bool view3d_main_region_draw_engine(const bContext *C, Scene *scene,
if (v3d->flag & V3D_DISPBGPICS)
view3d_draw_bgpic_test(scene, ar, v3d, false, true);
else
- fdrawcheckerboard(0, 0, ar->winx, ar->winy);
+ imm_draw_checker_box(0, 0, ar->winx, ar->winy);
/* render result draw */
type = rv3d->render_engine->type;
@@ -2541,7 +2356,7 @@ static void view3d_stereo3d_setup_offscreen(Scene *scene, View3D *v3d, ARegion *
static void update_lods(Scene *scene, float camera_pos[3])
{
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
for (SETLOOPER(scene, sce_iter, base)) {
Object *ob = base->object;
@@ -2550,7 +2365,7 @@ static void update_lods(Scene *scene, float camera_pos[3])
}
#endif
-static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, View3D *v3d,
+static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d,
ARegion *ar, const char **grid_unit)
{
wmWindow *win = CTX_wm_window(C);
@@ -2561,7 +2376,7 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
bool do_compositing = false;
/* shadow buffers, before we setup matrices */
- if (draw_glsl_material(scene, NULL, v3d, v3d->drawtype))
+ if (draw_glsl_material(scene, sl, NULL, v3d, v3d->drawtype))
gpu_update_lamps_shadows_world(scene, v3d);
/* reset default OpenGL lights if needed (i.e. after preferences have been altered) */
@@ -2602,9 +2417,6 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
do_compositing = GPU_fx_compositor_initialize_passes(rv3d->compositor, &ar->winrct, &ar->drawrct, &fx_settings);
}
- /* clear the background */
- view3d_main_region_clear(scene, v3d, ar);
-
/* enables anti-aliasing for 3D view drawing */
if (win->multisamples != USER_MULTISAMPLE_NONE) {
glEnable(GL_MULTISAMPLE);
@@ -2644,6 +2456,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
ARegion *ar, View3D *v3d,
const char *grid_unit, bool render_border)
{
+ SceneLayer *sl = CTX_data_scene_layer(C);
wmWindowManager *wm = CTX_wm_manager(C);
RegionView3D *rv3d = ar->regiondata;
rcti rect;
@@ -2664,7 +2477,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
}
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
- VP_legacy_drawcursor(scene, ar, v3d); /* 3D cursor */
+ VP_legacy_drawcursor(scene, sl, ar, v3d); /* 3D cursor */
if (U.uiflag & USER_SHOW_ROTVIEWICON)
VP_legacy_draw_view_axis(rv3d, &rect);
@@ -2672,9 +2485,8 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
draw_view_icon(rv3d, &rect);
if (U.uiflag & USER_DRAWVIEWINFO) {
- SceneLayer *sl = CTX_data_scene_layer(C);
Object *ob = OBACT_NEW;
- draw_selected_name(scene, ob, &rect);
+ VP_legacy_draw_selected_name(scene, ob, &rect);
}
}
@@ -2688,7 +2500,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
ED_scene_draw_fps(scene, &rect);
}
else if (U.uiflag & USER_SHOW_VIEWPORTNAME) {
- draw_viewport_name(ar, v3d, &rect);
+ VP_legacy_draw_viewport_name(ar, v3d, &rect);
}
if (grid_unit) { /* draw below the viewport name */
@@ -2709,6 +2521,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C);
const char *grid_unit = NULL;
rcti border_rect;
@@ -2718,22 +2531,36 @@ void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
+ glMatrixMode(GL_PROJECTION);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPushMatrix();
+ gpuLoadIdentity();
+
/* draw viewport using opengl */
if (v3d->drawtype != OB_RENDER || !view3d_main_region_do_render_draw(scene) || clip_border) {
- view3d_main_region_draw_objects(C, scene, v3d, ar, &grid_unit);
+ view3d_main_region_clear(scene, v3d, ar); /* background */
+ view3d_main_region_draw_objects(C, scene, sl, v3d, ar, &grid_unit);
if (G.debug & G_DEBUG_SIMDATA)
draw_sim_debug_data(scene, v3d, ar);
-
+
+ glDisable(GL_DEPTH_TEST);
ED_region_pixelspace(ar);
}
/* draw viewport using external renderer */
if (v3d->drawtype == OB_RENDER)
view3d_main_region_draw_engine(C, scene, ar, v3d, clip_border, &border_rect);
-
+
view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+ glMatrixMode(GL_PROJECTION);
+ gpuPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ gpuPopMatrix();
+
v3d->flag |= V3D_INVALID_BACKBUF;
BLI_assert(BLI_listbase_is_empty(&v3d->afterdraw_transp));
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index a27434fdfd7..6ba8f2b5a0f 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -90,19 +90,6 @@ bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
}
-static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op)
-{
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- if (ED_view3d_offset_lock_check(v3d, rv3d)) {
- BKE_report(op->reports, RPT_WARNING, "View offset is locked");
- return true;
- }
- else {
- return false;
- }
-}
-
/* ********************** view3d_edit: view manipulations ********************* */
/**
@@ -632,7 +619,8 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
bool is_set = false;
Scene *scene = CTX_data_scene(C);
- Object *ob_act = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob_act = OBACT_NEW;
if (ob_act && (ob_act->mode & OB_MODE_ALL_PAINT) &&
/* with weight-paint + pose-mode, fall through to using ED_calculateTransformCenter */
@@ -669,14 +657,13 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
}
else if (ob_act == NULL || ob_act->mode == OB_MODE_OBJECT) {
/* object mode use boundbox centers */
- View3D *v3d = CTX_wm_view3d(C);
- BaseLegacy *base;
+ Base *base;
unsigned int tot = 0;
float select_center[3];
zero_v3(select_center);
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (TESTBASE_NEW(base)) {
/* use the boundbox if we can */
Object *ob = base->object;
@@ -832,8 +819,9 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even
static void viewops_data_free(bContext *C, wmOperator *op)
{
ARegion *ar;
+#if 0
Paint *p = BKE_paint_get_active_from_context(C);
-
+#endif
if (op->customdata) {
ViewOpsData *vod = op->customdata;
ar = vod->ar;
@@ -849,7 +837,9 @@ static void viewops_data_free(bContext *C, wmOperator *op)
ar = CTX_wm_region(C);
}
+#if 0
if (p && (p->flags & PAINT_FAST_NAVIGATE))
+#endif
ED_region_tag_redraw(ar);
}
/** \} */
@@ -2596,6 +2586,19 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
/* ************************ viewdolly ******************************** */
+static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
+{
+ View3D *v3d = CTX_wm_view3d(C);
+ RegionView3D *rv3d = CTX_wm_region_view3d(C);
+ if (ED_view3d_offset_lock_check(v3d, rv3d)) {
+ BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
{
RegionView3D *rv3d = ar->regiondata;
@@ -2746,7 +2749,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
- if (view3d_operator_offset_lock_check(C, op))
+ if (viewdolly_offset_lock_check(C, op))
return OPERATOR_CANCELLED;
/* makes op->customdata */
@@ -2940,7 +2943,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
- BaseLegacy *base;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *base;
float *curs;
const bool use_all_regions = RNA_boolean_get(op->ptr, "use_all_regions");
const bool skip_camera = (ED_view3d_camera_lock_check(v3d, ar->regiondata) ||
@@ -2963,8 +2967,8 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
INIT_MINMAX(min, max);
}
- for (base = scene->base.first; base; base = base->next) {
- if (BASE_VISIBLE(v3d, base)) {
+ for (base = sl->object_bases.first; base; base = base->next) {
+ if (BASE_VISIBLE_NEW(base)) {
changed = true;
if (skip_camera && base->object == v3d->camera) {
@@ -3024,9 +3028,10 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
bGPdata *gpd = CTX_data_gpencil_data(C);
const bool is_gp_edit = ((gpd) && (gpd->flag & GP_DATA_STROKE_EDITMODE));
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
Object *obedit = CTX_data_edit_object(C);
float min[3], max[3];
bool ok = false, ok_dist = true;
@@ -3045,9 +3050,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
/* hard-coded exception, we look for the one selected armature */
/* this is weak code this way, we should make a generic active/selection callback interface once... */
- BaseLegacy *base;
+ Base *base;
for (base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ if (TESTBASELIB_NEW(base)) {
if (base->object->type == OB_ARMATURE)
if (base->object->mode & OB_MODE_POSE)
break;
@@ -3080,7 +3085,7 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok = paintface_minmax(ob, min, max);
}
else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) {
- ok = PE_minmax(scene, min, max);
+ ok = PE_minmax(scene, sl, min, max);
}
else if (ob &&
(ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)))
@@ -3091,9 +3096,9 @@ static int viewselected_exec(bContext *C, wmOperator *op)
ok_dist = 0; /* don't zoom */
}
else {
- BaseLegacy *base;
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ Base *base;
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (TESTBASE_NEW(base)) {
if (skip_camera && base->object == v3d->camera) {
continue;
@@ -3553,9 +3558,8 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
float new_ofs[3];
/* ZBuffer depth vars */
- bglMats mats;
float depth_close = FLT_MAX;
- double cent[2], p[3];
+ float p[3];
/* note; otherwise opengl won't work */
view3d_operator_needs_opengl(C);
@@ -3569,7 +3573,6 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
ED_view3d_dist_range_get(v3d, dist_range);
/* Get Z Depths, needed for perspective, nice for ortho */
- bgl_get_mats(&mats);
ED_view3d_draw_depth(scene, ar, v3d, true);
{
@@ -3585,11 +3588,11 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
MEM_SAFE_FREE(depth_temp.depths);
}
- cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2;
- cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2;
+ float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
if (rv3d->is_persp) {
- double p_corner[3];
+ float p_corner[3];
/* no depths to use, we cant do anything! */
if (depth_close == FLT_MAX) {
@@ -3597,23 +3600,14 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
- if ((!gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p[0], &p[1], &p[2])) ||
- (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p_corner[0], &p_corner[1], &p_corner[2])))
+ if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) ||
+ (!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
{
return OPERATOR_CANCELLED;
}
- dvec[0] = p[0] - p_corner[0];
- dvec[1] = p[1] - p_corner[1];
- dvec[2] = p[2] - p_corner[2];
-
- new_ofs[0] = -p[0];
- new_ofs[1] = -p[1];
- new_ofs[2] = -p[2];
+ sub_v3_v3v3(dvec, p, p_corner);
+ negate_v3_v3(new_ofs, p);
new_dist = len_v3(dvec);
@@ -3628,13 +3622,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport,
- &p[0], &p[1], &p[2]))
+ if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p))
{
- new_ofs[0] = -p[0];
- new_ofs[1] = -p[1];
- new_ofs[2] = -p[2];
+ negate_v3_v3(new_ofs, p);
}
else {
float mval_f[2];
@@ -3871,6 +3861,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
ARegion *ar;
RegionView3D *rv3d;
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
static int perspo = RV3D_PERSP;
int viewnum, nextperspo;
bool align_active;
@@ -3905,7 +3896,7 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
/* lastview - */
if (rv3d->persp != RV3D_CAMOB) {
- Object *ob = OBACT;
+ Object *ob = OBACT_NEW;
if (!rv3d->smooth_timer) {
/* store settings of current view before allowing overwriting with camera view
@@ -4364,41 +4355,24 @@ static EnumPropertyItem prop_view_pan_items[] = {
{0, NULL, 0, NULL, NULL}
};
-static int viewpan_exec(bContext *C, wmOperator *op)
+static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar = CTX_wm_region(C);
- View3D *v3d = CTX_wm_view3d(C);
- RegionView3D *rv3d = CTX_wm_region_view3d(C);
- float vec[3];
- const float co_zero[3] = {0.0f};
- float mval_f[2] = {0.0f, 0.0f};
- float zfac;
- int pandir;
-
- if (view3d_operator_offset_lock_check(C, op))
- return OPERATOR_CANCELLED;
-
- pandir = RNA_enum_get(op->ptr, "type");
-
- ED_view3d_camera_lock_init(v3d, rv3d);
+ int x = 0, y = 0;
+ int pandir = RNA_enum_get(op->ptr, "type");
- zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
- if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; }
- else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; }
- else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; }
- else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; }
- ED_view3d_win_to_delta(ar, mval_f, vec, zfac);
- add_v3_v3(rv3d->ofs, vec);
+ if (pandir == V3D_VIEW_PANRIGHT) { x = -32; }
+ else if (pandir == V3D_VIEW_PANLEFT) { x = 32; }
+ else if (pandir == V3D_VIEW_PANUP) { y = -25; }
+ else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
- if (rv3d->viewlock & RV3D_BOXVIEW)
- view3d_boxview_sync(sa, ar);
-
- ED_view3d_depth_tag_update(rv3d);
+ viewops_data_alloc(C, op);
+ viewops_data_create(C, op, event);
+ ViewOpsData *vod = op->customdata;
- ED_view3d_camera_lock_sync(v3d, rv3d);
+ viewmove_apply(vod, vod->oldx + x, vod->oldy + y);
- ED_region_tag_redraw(ar);
+ ED_view3d_depth_tag_update(vod->rv3d);
+ viewops_data_free(C, op);
return OPERATOR_FINISHED;
}
@@ -4411,7 +4385,7 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
ot->idname = "VIEW3D_OT_view_pan";
/* api callbacks */
- ot->exec = viewpan_exec;
+ ot->invoke = viewpan_invoke;
ot->poll = ED_operator_region_view3d_active;
/* flags */
@@ -4616,9 +4590,8 @@ void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[4][4])
static int view3d_clipping_exec(bContext *C, wmOperator *op)
{
+ ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
- ViewContext vc;
- bglMats mats;
rcti rect;
WM_operator_properties_border_to_rcti(op, &rect);
@@ -4626,12 +4599,8 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
rv3d->rflag |= RV3D_CLIPPING;
rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb");
- /* note; otherwise opengl won't work */
- view3d_operator_needs_opengl(C);
-
- view3d_set_viewcontext(C, &vc);
- view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because we don't want it in object space */
- ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, &mats, &rect);
+ /* NULL object because we don't want it in object space */
+ ED_view3d_clipping_calc(rv3d->clipbb, rv3d->clip, ar, NULL, &rect);
return OPERATOR_FINISHED;
}
@@ -4865,11 +4834,7 @@ static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
rect.ymax = mval[1] + 1;
}
else {
- rect.xmax = mval[0] + margin;
- rect.ymax = mval[1] + margin;
-
- rect.xmin = mval[0] - margin;
- rect.ymin = mval[1] - margin;
+ BLI_rcti_init_pt_radius(&rect, mval, margin);
}
view3d_update_depths_rect(ar, &depth_temp, &rect);
@@ -4890,9 +4855,7 @@ bool ED_view3d_autodist(
const int mval[2], float mouse_worldloc[3],
const bool alphaoverride, const float fallback_depth_pt[3])
{
- bglMats mats; /* ZBuffer depth vars */
float depth_close;
- double cent[2], p[3];
int margin_arr[] = {0, 2, 4};
int i;
bool depth_ok = false;
@@ -4900,9 +4863,6 @@ bool ED_view3d_autodist(
/* Get Z Depths, needed for perspective, nice for ortho */
ED_view3d_draw_depth(scene, ar, v3d, alphaoverride);
- /* call after in case settings have been modified since last drawing, see: T47089 */
- bgl_get_mats(&mats);
-
/* Attempt with low margin's first */
i = 0;
do {
@@ -4911,15 +4871,11 @@ bool ED_view3d_autodist(
} while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
if (depth_ok) {
- cent[0] = (double)mval[0] + 0.5;
- cent[1] = (double)mval[1] + 0.5;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
- if (gluUnProject(cent[0], cent[1], depth_close,
- mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
+ if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc))
{
- mouse_worldloc[0] = (float)p[0];
- mouse_worldloc[1] = (float)p[1];
- mouse_worldloc[2] = (float)p[2];
return true;
}
}
@@ -4950,9 +4906,7 @@ void ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode)
bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
int margin, float *force_depth)
{
- bglMats mats; /* ZBuffer depth vars, could cache? */
float depth;
- double cent[2], p[3];
/* Get Z Depths, needed for perspective, nice for ortho */
if (force_depth)
@@ -4963,21 +4917,9 @@ bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_world
if (depth == FLT_MAX)
return false;
- cent[0] = (double)mval[0] + 0.5;
- cent[1] = (double)mval[1] + 0.5;
-
- bgl_get_mats(&mats);
-
- if (!gluUnProject(cent[0], cent[1], depth,
- mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2]))
- {
- return false;
- }
-
- mouse_worldloc[0] = (float)p[0];
- mouse_worldloc[1] = (float)p[1];
- mouse_worldloc[2] = (float)p[2];
- return true;
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
}
bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index b42afd3a7a9..328e0b03bb8 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -259,8 +259,8 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
x2 = xoff + 0.55f * fly->width;
y2 = yoff + 0.55f * fly->height;
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 5f29e91143a..9566a3317cb 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -145,10 +145,12 @@ void draw_motion_paths_cleanup(View3D *v3d);
/* drawobject.c */
void draw_object(Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, BaseLegacy *base, const short dflag);
-void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm);
+void draw_object_select(Scene *scene, struct SceneLayer *sl, struct ARegion *ar, View3D *v3d, Base *base, const short dflag);
-bool draw_glsl_material(Scene *scene, struct Object *ob, View3D *v3d, const char dt);
-void draw_object_instance(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline);
+void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
+
+bool draw_glsl_material(Scene *scene, struct SceneLayer *sl, struct Object *ob, View3D *v3d, const char dt);
+void draw_object_instance(Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]);
void draw_object_backbufsel(Scene *scene, View3D *v3d, RegionView3D *rv3d, struct Object *ob);
void draw_object_wire_color(Scene *scene, struct SceneLayer *, Base *base, unsigned char r_ob_wire_col[4]);
@@ -159,8 +161,8 @@ void drawlamp(View3D *v3d, RegionView3D *rv3d, Base *base,
void drawcamera(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base,
const short dflag, const unsigned char ob_wire_col[4]);
void drawspeaker(const unsigned char ob_wire_col[3]);
-void draw_bounding_volume(struct Object *ob, char type);
-void draw_rigidbody_shape(struct Object *ob);
+void draw_bounding_volume(struct Object *ob, char type, const unsigned char ob_wire_col[4]);
+void draw_rigidbody_shape(struct Object *ob, const unsigned char ob_wire_col[4]);
void view3d_cached_text_draw_begin(void);
void view3d_cached_text_draw_add(const float co[3],
@@ -186,7 +188,7 @@ bool draw_armature(Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar
const bool is_outline);
/* drawmesh.c */
-void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
+void draw_mesh_textured(Scene *scene, struct SceneLayer *sl, View3D *v3d, RegionView3D *rv3d,
struct Object *ob, struct DerivedMesh *dm, const int draw_flags);
void draw_mesh_face_select(
struct RegionView3D *rv3d, struct Mesh *me, struct DerivedMesh *dm,
@@ -207,14 +209,18 @@ void draw_sim_debug_data(Scene *scene, View3D *v3d, ARegion *ar);
/* view3d_draw.c */
void view3d_main_region_draw(const struct bContext *C, struct ARegion *ar);
+void view3d_draw_region_info(const struct bContext *C, struct ARegion *ar);
/* view3d_draw_legacy.c */
void view3d_main_region_draw_legacy(const struct bContext *C, struct ARegion *ar);
void ED_view3d_draw_depth(Scene *scene, struct ARegion *ar, View3D *v3d, bool alphaoverride);
void ED_view3d_draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d);
+void ED_view3d_draw_select_loop(
+ ViewContext *vc, Scene *scene, struct SceneLayer *sl, View3D *v3d, ARegion *ar,
+ bool use_obedit_skip, bool use_nearest);
+
void ED_view3d_after_add(ListBase *lb, BaseLegacy *base, const short dflag);
-void circ(float x, float y, float rad);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
float view3d_depth_near(struct ViewDepths *d);
@@ -257,7 +263,7 @@ void ED_view3d_smooth_view_force_finish(
struct bContext *C,
struct View3D *v3d, struct ARegion *ar);
-void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect);
+void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect);
void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
@@ -329,8 +335,10 @@ extern bool view3d_camera_border_hack_test;
#define IS_VIEWPORT_LEGACY(v3d) ((v3d->tmp_compat_flag & V3D_NEW_VIEWPORT) == 0)
/* temporary for legacy viewport to work */
-void VP_legacy_drawcursor(Scene *scene, ARegion *ar, View3D *v3d);
+void VP_legacy_drawcursor(Scene *scene, struct SceneLayer *sl, ARegion *ar, View3D *v3d);
void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect);
+void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect);
+void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect);
void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
void VP_legacy_view3d_main_region_setup_view(Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index 65a6dee2f6c..f8b02f0b405 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -36,14 +36,13 @@
#include "BLI_sys_types.h" /* int64_t */
-#include "BIF_gl.h" /* bglMats */
-#include "BIF_glutil.h" /* bglMats */
-
#include "BLI_math_vector.h"
#include "BKE_camera.h"
#include "BKE_screen.h"
+#include "GPU_matrix.h"
+
#include "ED_view3d.h" /* own include */
#define BL_NEAR_CLIP 0.001
@@ -656,16 +655,22 @@ void ED_view3d_ob_project_mat_get_from_obmat(const RegionView3D *rv3d, float obm
}
/**
- * Uses window coordinates (x,y) and depth component z to find a point in
- * modelspace */
-void ED_view3d_unproject(bglMats *mats, float out[3], const float x, const float y, const float z)
+ * Convert between region relative coordinates (x,y) and depth component z and
+ * a point in world space. */
+void ED_view3d_project(const struct ARegion *ar, const float world[3], float region[3])
{
- double ux, uy, uz;
+ // viewport is set up to make coordinates relative to the region, not window
+ RegionView3D *rv3d = ar->regiondata;
+ int viewport[4] = {0, 0, ar->winx, ar->winy};
- gluUnProject(x, y, z, mats->modelview, mats->projection,
- (GLint *)mats->viewport, &ux, &uy, &uz);
+ gpuProject(world, rv3d->viewmat, rv3d->winmat, viewport, region);
+}
+
+bool ED_view3d_unproject(const struct ARegion *ar, float regionx, float regiony, float regionz, float world[3])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ int viewport[4] = {0, 0, ar->winx, ar->winy};
+ float region[3] = {regionx, regiony, regionz};
- out[0] = ux;
- out[1] = uy;
- out[2] = uz;
+ return gpuUnProject(region, rv3d->viewmat, rv3d->winmat, viewport, world);
}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 60bf078acc3..76f8db1cec5 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -75,7 +75,6 @@
#include "BKE_utildefines.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "WM_api.h"
@@ -97,9 +96,12 @@
#include "UI_interface.h"
#include "GPU_draw.h"
+#include "GPU_matrix.h"
#include "view3d_intern.h" /* own include */
+// #include "PIL_time_utildefines.h"
+
float ED_view3d_select_dist_px(void)
{
return 75.0f * U.pixelsize;
@@ -119,34 +121,6 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
vc->obedit = CTX_data_edit_object(C);
}
-/*
- * ob == NULL if you want global matrices
- * */
-void view3d_get_transformation(const ARegion *ar, RegionView3D *rv3d, Object *ob, bglMats *mats)
-{
- float cpy[4][4];
- int i, j;
-
- if (ob) {
- mul_m4_m4m4(cpy, rv3d->viewmat, ob->obmat);
- }
- else {
- copy_m4_m4(cpy, rv3d->viewmat);
- }
-
- for (i = 0; i < 4; ++i) {
- for (j = 0; j < 4; ++j) {
- mats->projection[i * 4 + j] = rv3d->winmat[i][j];
- mats->modelview[i * 4 + j] = cpy[i][j];
- }
- }
-
- mats->viewport[0] = ar->winrct.xmin;
- mats->viewport[1] = ar->winrct.ymin;
- mats->viewport[2] = ar->winx;
- mats->viewport[3] = ar->winy;
-}
-
/* ********************** view3d_select: selection manipulations ********************* */
/* local prototypes */
@@ -503,7 +477,7 @@ static void do_lasso_select_mesh(ViewContext *vc, const int mcords[][2], short m
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
+ gpuLoadMatrix3D(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
@@ -1087,7 +1061,9 @@ static void deselectall_except(SceneLayer *sl, Base *b) /* deselect all except
}
}
-static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle)
+static Base *object_mouse_select_menu(
+ bContext *C, ViewContext *vc, unsigned int *buffer, int hits,
+ const int mval[2], bool toggle)
{
short baseCount = 0;
bool ok;
@@ -1179,19 +1155,19 @@ static bool selectbuffer_has_bones(const unsigned int *buffer, const unsigned in
}
/* utility function for mixed_bones_object_selectbuffer */
-static short selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const short hits15)
+static int selectbuffer_ret_hits_15(unsigned int *UNUSED(buffer), const int hits15)
{
return hits15;
}
-static short selectbuffer_ret_hits_9(unsigned int *buffer, const short hits15, const short hits9)
+static int selectbuffer_ret_hits_9(unsigned int *buffer, const int hits15, const int hits9)
{
const int offs = 4 * hits15;
memcpy(buffer, buffer + offs, 4 * hits9 * sizeof(unsigned int));
return hits9;
}
-static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, const short hits9, const short hits5)
+static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits15, const int hits9, const int hits5)
{
const int offs = 4 * hits15 + 4 * hits9;
memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
@@ -1200,14 +1176,13 @@ static short selectbuffer_ret_hits_5(unsigned int *buffer, const short hits15, c
/* we want a select buffer with bones, if there are... */
/* so check three selection levels and compare */
-static short mixed_bones_object_selectbuffer(
+static int mixed_bones_object_selectbuffer(
ViewContext *vc, unsigned int *buffer, const int mval[2],
bool use_cycle, bool enumerate,
bool *r_do_nearest)
{
rcti rect;
- int offs;
- short hits15, hits9 = 0, hits5 = 0;
+ int hits15, hits9 = 0, hits5 = 0;
bool has_bones15 = false, has_bones9 = false, has_bones5 = false;
static int last_mval[2] = {-100, -100};
bool do_nearest = false;
@@ -1235,44 +1210,57 @@ static short mixed_bones_object_selectbuffer(
do_nearest = do_nearest && !enumerate;
- BLI_rcti_init(&rect, mval[0] - 14, mval[0] + 14, mval[1] - 14, mval[1] + 14);
- hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, do_nearest);
+ const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
+ int hits = 0;
+
+ /* we _must_ end cache before return, use 'goto finally' */
+ view3d_opengl_select_cache_begin();
+
+ BLI_rcti_init_pt_radius(&rect, mval, 14);
+ hits15 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
if (hits15 == 1) {
- return selectbuffer_ret_hits_15(buffer, hits15);
+ hits = selectbuffer_ret_hits_15(buffer, hits15);
+ goto finally;
}
else if (hits15 > 0) {
+ int offs;
has_bones15 = selectbuffer_has_bones(buffer, hits15);
offs = 4 * hits15;
- BLI_rcti_init(&rect, mval[0] - 9, mval[0] + 9, mval[1] - 9, mval[1] + 9);
- hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
+ BLI_rcti_init_pt_radius(&rect, mval, 9);
+ hits9 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
if (hits9 == 1) {
- return selectbuffer_ret_hits_9(buffer, hits15, hits9);
+ hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
+ goto finally;
}
else if (hits9 > 0) {
has_bones9 = selectbuffer_has_bones(buffer + offs, hits9);
offs += 4 * hits9;
- BLI_rcti_init(&rect, mval[0] - 5, mval[0] + 5, mval[1] - 5, mval[1] + 5);
- hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, do_nearest);
+ BLI_rcti_init_pt_radius(&rect, mval, 5);
+ hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
if (hits5 == 1) {
- return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+ hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
+ goto finally;
}
else if (hits5 > 0) {
has_bones5 = selectbuffer_has_bones(buffer + offs, hits5);
}
}
- if (has_bones5) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
- else if (has_bones9) return selectbuffer_ret_hits_9(buffer, hits15, hits9);
- else if (has_bones15) return selectbuffer_ret_hits_15(buffer, hits15);
-
- if (hits5 > 0) return selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
- else if (hits9 > 0) return selectbuffer_ret_hits_9(buffer, hits15, hits9);
- else return selectbuffer_ret_hits_15(buffer, hits15);
+ if (has_bones5) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
+ else if (has_bones9) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
+ else if (has_bones15) { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
+
+ if (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5); goto finally; }
+ else if (hits9 > 0) { hits = selectbuffer_ret_hits_9(buffer, hits15, hits9); goto finally; }
+ else { hits = selectbuffer_ret_hits_15(buffer, hits15); goto finally; }
}
-
- return 0;
+
+finally:
+ view3d_opengl_select_cache_end();
+
+ return hits;
}
/* returns basact */
@@ -1412,7 +1400,7 @@ static bool ed_object_select_pick(
bool is_obedit;
float dist = ED_view3d_select_dist_px() * 1.3333f;
bool retval = false;
- short hits;
+ int hits;
const float mval_fl[2] = {(float)mval[0], (float)mval[1]};
@@ -1464,10 +1452,13 @@ static bool ed_object_select_pick(
unsigned int buffer[MAXPICKBUF];
bool do_nearest;
+ // TIMEIT_START(select_time);
+
/* if objects have posemode set, the bones are in the same selection buffer */
-
hits = mixed_bones_object_selectbuffer(&vc, buffer, mval, true, enumerate, &do_nearest);
-
+
+ // TIMEIT_END(select_time);
+
if (hits > 0) {
/* note: bundles are handling in the same way as bones */
const bool has_bones = selectbuffer_has_bones(buffer, hits);
@@ -1539,7 +1530,7 @@ static bool ed_object_select_pick(
}
}
}
- else if (ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
+ else if (ED_do_pose_selectbuffer(scene, sl, basact, buffer, hits, extend, deselect, toggle, do_nearest)) {
/* then bone is found */
/* we make the armature selected:
@@ -1858,7 +1849,7 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
/* for non zbuf projections, don't change the GL state */
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
- glLoadMatrixf(vc->rv3d->viewmat);
+ gpuLoadMatrix3D(vc->rv3d->viewmat);
bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
if (ts->selectmode & SCE_SELECT_VERTEX) {
@@ -1904,9 +1895,9 @@ static int do_meta_box_select(ViewContext *vc, rcti *rect, bool select, bool ext
int a;
unsigned int buffer[MAXPICKBUF];
- short hits;
+ int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
if (extend == false && select)
BKE_mball_deselect_all(mb);
@@ -1938,9 +1929,9 @@ static int do_armature_box_select(ViewContext *vc, rcti *rect, bool select, bool
int a;
unsigned int buffer[MAXPICKBUF];
- short hits;
+ int hits;
- hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, false);
+ hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL);
/* clear flag we use to detect point was affected */
for (ebone = arm->edbo->first; ebone; ebone = ebone->next)
@@ -2013,7 +2004,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
int bone_only;
int bone_selected = 0;
int totobj = MAXPICKBUF; /* XXX solve later */
- short hits;
+ int hits;
if ((ob) && (ob->mode & OB_MODE_POSE))
bone_only = 1;
@@ -2037,7 +2028,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(unsigned int), "selection buffer");
- hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, false);
+ hits = view3d_opengl_select(vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL);
/*
* LOGIC NOTES (theeth):
* The buffer and ListBase have the same relative order, which makes the selection
@@ -2051,11 +2042,11 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
*/
if (hits > 0) { /* no need to loop if there's no hit */
- BaseLegacy *base;
+ Base *base;
col = vbuffer + 3;
- for (base = vc->scene->base.first; base && hits; base = base->next) {
- if (BASE_SELECTABLE(vc->v3d, base)) {
+ for (base = vc->sl->object_bases.first; base && hits; base = base->next) {
+ if (BASE_SELECTABLE_NEW(base)) {
while (base->selcol == (*col & 0xFFFF)) { /* we got an object */
if (*col & 0xFFFF0000) { /* we got a bone */
bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY));
@@ -2075,7 +2066,7 @@ static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, b
}
}
else if (!bone_only) {
- ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT);
+ ED_object_base_select(base, select ? BA_SELECT : BA_DESELECT);
}
col += 4; /* next color */
@@ -2577,7 +2568,7 @@ static void lattice_circle_select(ViewContext *vc, const bool select, const int
/* NOTE: pose-bone case is copied from editbone case... */
-static short pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2])
+static bool pchan_circle_doSelectJoint(void *userData, bPoseChannel *pchan, const float screen_co[2])
{
CircleSelectUserData *data = userData;
@@ -2655,7 +2646,7 @@ static void pose_circle_select(ViewContext *vc, const bool select, const int mva
}
}
-static short armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], short head)
+static bool armature_circle_doSelectJoint(void *userData, EditBone *ebone, const float screen_co[2], bool head)
{
CircleSelectUserData *data = userData;
diff --git a/source/blender/editors/space_view3d/view3d_transform_manipulators.c b/source/blender/editors/space_view3d/view3d_transform_manipulators.c
index b02769c6d09..57bd49dd3fb 100644
--- a/source/blender/editors/space_view3d/view3d_transform_manipulators.c
+++ b/source/blender/editors/space_view3d/view3d_transform_manipulators.c
@@ -555,12 +555,12 @@ static int transform_manipulators_protectflag_editmode_get(Object *obedit, View3
return protectflag;
}
-static int transform_manipulators_protectflag_objectmode_get(const Scene *scene, const View3D *v3d)
+static int transform_manipulators_protectflag_objectmode_get(const Scene *scene)
{
int protectflag = 0;
for (Base *base = scene->base.first; base; base = base->next) {
- if (TESTBASELIB(v3d, base)) {
+ if (TESTBASELIB_NEW(base)) {
protectflag |= base->object->protectflag;
}
}
@@ -589,7 +589,7 @@ static int transform_manipulators_protectflag_get(const bContext *C, View3D *v3d
/* pass */
}
else {
- protectflag = transform_manipulators_protectflag_objectmode_get(scene, v3d);
+ protectflag = transform_manipulators_protectflag_objectmode_get(scene);
}
return protectflag;
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 53c91936913..e29f00c2ec2 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -51,10 +51,10 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
#include "GPU_select.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -96,10 +96,8 @@ void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
RegionView3D *rv3d = ar->regiondata;
wmSubWindowSet(win, ar->swinid);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(rv3d->winmat);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(rv3d->viewmat);
+ gpuLoadProjectionMatrix3D(rv3d->winmat);
+ gpuLoadMatrix3D(rv3d->viewmat);
}
}
@@ -539,6 +537,7 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
Object *camera_ob = v3d ? v3d->camera : scene->camera;
@@ -551,7 +550,7 @@ static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
}
/* this function does all the important stuff */
- if (BKE_camera_view_frame_fit_to_scene(scene, v3d, camera_ob, r_co, &r_scale)) {
+ if (BKE_camera_view_frame_fit_to_scene(scene, sl, camera_ob, r_co, &r_scale)) {
ObjectTfmProtectedChannels obtfm;
float obmat_new[4][4];
@@ -725,40 +724,35 @@ void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb,
}
}
-void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
+void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
{
- float modelview[4][4];
- double xs, ys, p[3];
- int val, flip_sign, a;
-
- /* near zero floating point values can give issues with gluUnProject
- * in side view on some implementations */
- if (fabs(mats->modelview[0]) < 1e-6) mats->modelview[0] = 0.0;
- if (fabs(mats->modelview[5]) < 1e-6) mats->modelview[5] = 0.0;
-
- /* Set up viewport so that gluUnProject will give correct values */
- mats->viewport[0] = 0;
- mats->viewport[1] = 0;
+ /* init in case unproject fails */
+ memset(bb->vec, 0, sizeof(bb->vec));
/* four clipping planes and bounding volume */
/* first do the bounding volume */
- for (val = 0; val < 4; val++) {
- xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
- ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
+ for (int val = 0; val < 4; val++) {
+ float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
+ float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
+
+ ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
+ ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
+ }
- gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
- copy_v3fl_v3db(bb->vec[val], p);
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
- gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
- copy_v3fl_v3db(bb->vec[4 + val], p);
+ for (int val = 0; val < 8; val++) {
+ mul_m4_v3(imat, bb->vec[val]);
+ }
}
/* verify if we have negative scale. doing the transform before cross
* product flips the sign of the vector compared to doing cross product
* before transform then, so we correct for that. */
- for (a = 0; a < 16; a++)
- ((float *)modelview)[a] = mats->modelview[a];
- flip_sign = is_negative_m4(modelview);
+ int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
}
@@ -908,7 +902,7 @@ void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
/**
* \param rect optional for picking (can be NULL).
*/
-void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect)
+void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
rctf viewplane;
@@ -934,14 +928,14 @@ void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rctf *rect)
}
if (is_ortho) {
- wmOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ gpuOrtho(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
else {
- wmFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
+ gpuFrustum(viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend);
}
/* update matrix in 3d view region */
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)rv3d->winmat);
+ gpuGetProjectionMatrix3D(rv3d->winmat);
}
static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
@@ -1091,75 +1085,19 @@ void view3d_viewmatrix_set(Scene *scene, const View3D *v3d, RegionView3D *rv3d)
}
}
-static void view3d_select_loop(ViewContext *vc, Scene *scene, SceneLayer *sl, View3D *v3d, ARegion *ar, bool use_obedit_skip)
+/**
+ * Optionally cache data for multiple calls to #view3d_opengl_select
+ *
+ * just avoid GPU_select headers outside this file
+ */
+void view3d_opengl_select_cache_begin(void)
{
- short code = 1;
- char dt;
- short dtx;
-
- if (vc->obedit && vc->obedit->type == OB_MBALL) {
- draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- else if ((vc->obedit && vc->obedit->type == OB_ARMATURE)) {
- /* if not drawing sketch, draw bones */
- if (!BDR_drawSketchNames(vc)) {
- draw_object(scene, sl, ar, v3d, BASACT_NEW, DRAW_PICKING | DRAW_CONSTCOLOR);
- }
- }
- else {
- Base *base;
-
- v3d->xray = true; /* otherwise it postpones drawing */
- for (base = sl->object_bases.first; base; base = base->next) {
- if ((base->flag & BASE_VISIBLED) != 0) {
- if ((base->object->restrictflag & OB_RESTRICT_SELECT) ||
- (use_obedit_skip && (scene->obedit->data == base->object->data)))
- {
- base->selcol = 0;
- }
- else {
- base->selcol = code;
-
- if (GPU_select_load_id(code)) {
- draw_object(scene, sl, ar, v3d, base, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- /* we draw duplicators for selection too */
- if ((base->object->transflag & OB_DUPLI)) {
- ListBase *lb;
- DupliObject *dob;
- Base tbase;
-
- tbase.flag_legacy = OB_FROMDUPLI;
- lb = object_duplilist(G.main->eval_ctx, scene, base->object);
-
- for (dob = lb->first; dob; dob = dob->next) {
- float omat[4][4];
-
- tbase.object = dob->ob;
- copy_m4_m4(omat, dob->ob->obmat);
- copy_m4_m4(dob->ob->obmat, dob->mat);
-
- /* extra service: draw the duplicator in drawtype of parent */
- /* MIN2 for the drawtype to allow bounding box objects in groups for lods */
- dt = tbase.object->dt; tbase.object->dt = MIN2(tbase.object->dt, base->object->dt);
- dtx = tbase.object->dtx; tbase.object->dtx = base->object->dtx;
-
- draw_object(scene, sl, ar, v3d, &tbase, DRAW_PICKING | DRAW_CONSTCOLOR);
-
- tbase.object->dt = dt;
- tbase.object->dtx = dtx;
+ GPU_select_cache_begin();
+}
- copy_m4_m4(dob->ob->obmat, omat);
- }
- free_object_duplilist(lb);
- }
- }
- code++;
- }
- }
- }
- v3d->xray = false; /* restore */
- }
+void view3d_opengl_select_cache_end(void)
+{
+ GPU_select_cache_end();
}
/**
@@ -1169,30 +1107,66 @@ static void view3d_select_loop(ViewContext *vc, Scene *scene, SceneLayer *sl, Vi
*
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
*/
-short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input, bool do_nearest)
+int view3d_opengl_select(
+ ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const rcti *input,
+ eV3DSelectMode select_mode)
{
Scene *scene = vc->scene;
SceneLayer *sl = vc->sl;
View3D *v3d = vc->v3d;
ARegion *ar = vc->ar;
- rctf rect;
- short hits;
+ rcti rect;
+ int hits;
const bool use_obedit_skip = (scene->obedit != NULL) && (vc->obedit == NULL);
- const bool do_passes = do_nearest && GPU_select_query_check_active();
+ const bool is_pick_select = (U.gpu_select_pick_deph != 0);
+ const bool do_passes = (
+ (is_pick_select == false) &&
+ (select_mode == VIEW3D_SELECT_PICK_NEAREST) &&
+ GPU_select_query_check_active());
+ const bool use_nearest = (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST);
+
+ char gpu_select_mode;
- G.f |= G_PICKSEL;
-
/* case not a border select */
if (input->xmin == input->xmax) {
- rect.xmin = input->xmin - 12; /* seems to be default value for bones only now */
- rect.xmax = input->xmin + 12;
- rect.ymin = input->ymin - 12;
- rect.ymax = input->ymin + 12;
+ /* seems to be default value for bones only now */
+ BLI_rcti_init_pt_radius(&rect, (const int[2]){input->xmin, input->ymin}, 12);
}
else {
- BLI_rctf_rcti_copy(&rect, input);
+ rect = *input;
}
-
+
+ if (is_pick_select) {
+ if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_NEAREST) {
+ gpu_select_mode = GPU_SELECT_PICK_NEAREST;
+ }
+ else if (is_pick_select && select_mode == VIEW3D_SELECT_PICK_ALL) {
+ gpu_select_mode = GPU_SELECT_PICK_ALL;
+ }
+ else {
+ gpu_select_mode = GPU_SELECT_ALL;
+ }
+ }
+ else {
+ if (do_passes) {
+ gpu_select_mode = GPU_SELECT_NEAREST_FIRST_PASS;
+ }
+ else {
+ gpu_select_mode = GPU_SELECT_ALL;
+ }
+ }
+
+ /* Re-use cache (rect must be smaller then the cached)
+ * other context is assumed to be unchanged */
+ if (GPU_select_is_cached()) {
+ GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
+ GPU_select_cache_load_id();
+ hits = GPU_select_end();
+ goto finally;
+ }
+
+ G.f |= G_PICKSEL;
+
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(vc->rv3d->persmat, vc->rv3d->winmat, vc->rv3d->viewmat);
@@ -1204,12 +1178,9 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_set(vc->rv3d);
- if (do_passes)
- GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
- else
- GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_ALL, 0);
+ GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
- view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip);
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
hits = GPU_select_end();
@@ -1217,7 +1188,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (do_passes) {
GPU_select_begin(buffer, bufsize, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
- view3d_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip);
+ ED_view3d_draw_select_loop(vc, scene, sl, v3d, ar, use_obedit_skip, use_nearest);
GPU_select_end();
}
@@ -1233,7 +1204,8 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
if (vc->rv3d->rflag & RV3D_CLIPPING)
ED_view3d_clipping_disable();
-
+
+finally:
if (hits < 0) printf("Too many objects in select buffer\n"); /* XXX make error message */
return hits;
@@ -1315,11 +1287,11 @@ int ED_view3d_scene_layer_set(int lay, const int *values, int *active)
static bool view3d_localview_init(
wmWindowManager *wm, wmWindow *win,
- Main *bmain, Scene *scene, ScrArea *sa, const int smooth_viewtx,
+ Main *bmain, Scene *scene, SceneLayer *sl, ScrArea *sa, const int smooth_viewtx,
ReportList *reports)
{
View3D *v3d = sa->spacedata.first;
- BaseLegacy *base;
+ Base *base;
float min[3], max[3], box[3], mid[3];
float size = 0.0f;
unsigned int locallay;
@@ -1343,12 +1315,12 @@ static bool view3d_localview_init(
ok = true;
- BASACT->lay |= locallay;
- scene->obedit->lay = BASACT->lay;
+ BASACT_NEW->lay |= locallay;
+ scene->obedit->lay = BASACT_NEW->lay;
}
else {
- for (base = FIRSTBASE; base; base = base->next) {
- if (TESTBASE(v3d, base)) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
+ if (TESTBASE_NEW(base)) {
BKE_object_minmax(base->object, min, max, false);
base->lay |= locallay;
base->object->lay = base->lay;
@@ -1418,16 +1390,18 @@ static bool view3d_localview_init(
}
else {
/* clear flags */
- for (base = FIRSTBASE; base; base = base->next) {
+ for (base = FIRSTBASE_NEW; base; base = base->next) {
if (base->lay & locallay) {
base->lay -= locallay;
if (base->lay == 0) base->lay = v3d->layact;
- if (base->object != scene->obedit) base->flag_legacy |= SELECT;
+ if (base->object != scene->obedit) base->flag |= BASE_SELECTED;
base->object->lay = base->lay;
}
}
}
+ DAG_on_visible_update(bmain, false);
+
return ok;
}
@@ -1533,6 +1507,7 @@ static int localview_exec(bContext *C, wmOperator *op)
wmWindow *win = CTX_wm_window(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = CTX_wm_view3d(C);
bool changed;
@@ -1541,7 +1516,7 @@ static int localview_exec(bContext *C, wmOperator *op)
changed = view3d_localview_exit(wm, win, bmain, scene, sa, smooth_viewtx);
}
else {
- changed = view3d_localview_init(wm, win, bmain, scene, sa, smooth_viewtx, op->reports);
+ changed = view3d_localview_init(wm, win, bmain, scene, sl, sa, smooth_viewtx, op->reports);
}
if (changed) {
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index d4e78035b84..8390d56c610 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -340,8 +340,8 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
yoff = walk->ar->winy / 2;
}
- VertexFormat* format = immVertexFormat();
- unsigned pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
+ VertexFormat *format = immVertexFormat();
+ unsigned int pos = add_attrib(format, "pos", GL_INT, 2, CONVERT_INT_TO_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index fb1543c5deb..366dcc4dc21 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -1717,9 +1717,10 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
projectFloatViewEx(t, vecrot, cent, V3D_PROJ_TEST_CLIP_ZERO);
- gpuMatrixBegin3D_legacy(); /* TODO(merwin): finish the 2D matrix API & use here */
+ gpuPushMatrix();
unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 2, KEEP_FLOAT);
+ UNUSED_VARS(pos); /* silence warning */
BLI_assert(pos == POS_INDEX);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
@@ -1824,7 +1825,7 @@ static void drawHelpline(bContext *UNUSED(C), int x, int y, void *customdata)
}
immUnbindProgram();
- gpuMatrixEnd();
+ gpuPopMatrix();
}
}
@@ -2191,7 +2192,14 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
calculateCenter(t);
if (event) {
- initMouseInput(t, &t->mouse, t->center2d, event->mval, event->shift);
+ /* Initialize accurate transform to settings requested by keymap. */
+ bool use_accurate = false;
+ if ((prop = RNA_struct_find_property(op->ptr, "use_accurate")) && RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop)) {
+ use_accurate = true;
+ }
+ }
+ initMouseInput(t, &t->mouse, t->center2d, event->mval, use_accurate);
}
switch (mode) {
@@ -6841,8 +6849,7 @@ static void drawEdgeSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gpuMatrixBegin3D_legacy();
-
+ gpuPushMatrix();
gpuMultMatrix3D(t->obedit->obmat);
unsigned pos = add_attrib(immVertexFormat(), "pos", COMP_F32, 3, KEEP_FLOAT);
@@ -6930,7 +6937,7 @@ static void drawEdgeSlide(TransInfo *t)
immUnbindProgram();
- gpuMatrixEnd();
+ gpuPopMatrix();
glDisable(GL_BLEND);
@@ -7454,8 +7461,7 @@ static void drawVertSlide(TransInfo *t)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- gpuMatrixBegin3D_legacy();
-
+ gpuPushMatrix();
gpuMultMatrix3D(t->obedit->obmat);
glLineWidth(line_size);
@@ -7534,7 +7540,7 @@ static void drawVertSlide(TransInfo *t)
immUnbindProgram();
- gpuMatrixEnd();
+ gpuPopMatrix();
if (v3d && v3d->zbuf)
glEnable(GL_DEPTH_TEST);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 31af54c030b..a292b27e2b3 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -50,6 +50,7 @@ struct Object;
struct View3D;
struct ScrArea;
struct Scene;
+struct SceneLayer;
struct bConstraint;
struct wmKeyMap;
struct wmKeyConfig;
@@ -644,7 +645,7 @@ bool transdata_check_local_islands(TransInfo *t, short around);
int count_set_pose_transflags(int *out_mode, short around, struct Object *ob);
/* auto-keying stuff used by special_aftertrans_update */
-void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode);
+void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct SceneLayer *sl, struct View3D *v3d, struct Object *ob, int tmode);
void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik);
/*********************** Constraints *****************************/
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index d123d9eb3c1..5936f215c62 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -43,6 +43,7 @@
#include "BIF_glutil.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -778,13 +779,13 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
unit_m4(imat);
}
- glPushMatrix();
+ gpuPushMatrix();
if (t->spacetype == SPACE_VIEW3D) {
/* pass */
}
else if (t->spacetype == SPACE_IMAGE) {
- glScalef(1.0f / t->aspect[0], 1.0f / t->aspect[1], 1.0f);
+ gpuScale2f(1.0f / t->aspect[0], 1.0f / t->aspect[1]);
}
else if (ELEM(t->spacetype, SPACE_IPO, SPACE_ACTION)) {
/* only scale y */
@@ -794,7 +795,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
float ysize = BLI_rctf_size_y(datamask);
float xmask = BLI_rcti_size_x(mask);
float ymask = BLI_rcti_size_y(mask);
- glScalef(1.0f, (ysize / xsize) * (xmask / ymask), 1.0f);
+ gpuScale2f(1.0f, (ysize / xsize) * (xmask / ymask));
}
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
@@ -815,7 +816,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t)
if (depth_test_enabled)
glEnable(GL_DEPTH_TEST);
- glPopMatrix();
+ gpuPopMatrix();
}
}
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index b68b3365e46..c09434a3bc9 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -286,13 +286,13 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
static void createTransTexspace(TransInfo *t)
{
- Scene *scene = t->scene;
+ SceneLayer *sl = t->sl;
TransData *td;
Object *ob;
ID *id;
short *texflag;
- ob = OBACT;
+ ob = OBACT_NEW;
if (ob == NULL) { // Shouldn't logically happen, but still...
t->total = 0;
@@ -1800,7 +1800,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
Base *base = CTX_data_active_base(C);
Object *ob = CTX_data_active_object(C);
ParticleEditSettings *pset = PE_settings(t->scene);
- PTCacheEdit *edit = PE_get_current(t->scene, ob);
+ PTCacheEdit *edit = PE_get_current(t->scene, t->sl, ob);
ParticleSystem *psys = NULL;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -1917,8 +1917,9 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
void flushTransParticles(TransInfo *t)
{
Scene *scene = t->scene;
- Object *ob = OBACT;
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ SceneLayer *sl = t->sl;
+ Object *ob = OBACT_NEW;
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = NULL;
PTCacheEditPoint *point;
@@ -1957,14 +1958,17 @@ void flushTransParticles(TransInfo *t)
point->flag |= PEP_EDIT_RECALC;
}
- PE_update_object(scene, OBACT, 1);
+ PE_update_object(scene, sl, OBACT_NEW, 1);
}
/* ********************* mesh ****************** */
-static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
- float *dists, const float *dists_prev,
- float mtx[3][3])
+static bool bmesh_test_dist_add(
+ BMVert *v, BMVert *v_other,
+ float *dists, const float *dists_prev,
+ /* optionally track original index */
+ int *index, const int *index_prev,
+ float mtx[3][3])
{
if ((BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) &&
(BM_elem_flag_test(v_other, BM_ELEM_HIDDEN) == 0))
@@ -1979,6 +1983,9 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
dist_other = dists_prev[i] + len_v3(vec);
if (dist_other < dists[i_other]) {
dists[i_other] = dist_other;
+ if (index != NULL) {
+ index[i_other] = index_prev[i];
+ }
return true;
}
}
@@ -1986,11 +1993,13 @@ static bool bmesh_test_dist_add(BMVert *v, BMVert *v_other,
return false;
}
-static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists)
+/**
+ * \parm mtx: Measure disatnce in this space.
+ * \parm dists: Store the closest connected distance to selected vertices.
+ * \parm index: Optionally store the original index we're measuring the distance to (can be NULL).
+ */
+static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float *dists, int *index)
{
- /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
- float *dists_prev = MEM_mallocN(bm->totvert * sizeof(float), __func__);
-
BLI_LINKSTACK_DECLARE(queue, BMVert *);
/* any BM_ELEM_TAG'd vertex is in 'queue_next', so we don't add in twice */
@@ -2011,17 +2020,27 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
if (BM_elem_flag_test(v, BM_ELEM_SELECT) == 0 || BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
dist = FLT_MAX;
+ if (index != NULL) {
+ index[i] = i;
+ }
}
else {
BLI_LINKSTACK_PUSH(queue, v);
dist = 0.0f;
+ if (index != NULL) {
+ index[i] = i;
+ }
}
- dists[i] = dists_prev[i] = dist;
+ dists[i] = dist;
}
bm->elem_index_dirty &= ~BM_VERT;
}
+ /* need to be very careful of feedback loops here, store previous dist's to avoid feedback */
+ float *dists_prev = MEM_dupallocN(dists);
+ int *index_prev = MEM_dupallocN(index); /* may be NULL */
+
do {
BMVert *v;
LinkNode *lnk;
@@ -2050,7 +2069,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
/* edge distance */
{
BMVert *v_other = BM_edge_other_vert(e_iter, v);
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
@@ -2075,7 +2094,7 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
(BM_elem_flag_test(l_iter_radial->f, BM_ELEM_HIDDEN) == 0))
{
BMVert *v_other = l_iter_radial->next->next->v;
- if (bmesh_test_dist_add(v, v_other, dists, dists_prev, mtx)) {
+ if (bmesh_test_dist_add(v, v_other, dists, dists_prev, index, index_prev, mtx)) {
if (BM_elem_flag_test(v_other, BM_ELEM_TAG) == 0) {
BM_elem_flag_enable(v_other, BM_ELEM_TAG);
BLI_LINKSTACK_PUSH(queue_next, v_other);
@@ -2099,6 +2118,9 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
/* keep in sync, avoid having to do full memcpy each iteration */
dists_prev[i] = dists[i];
+ if (index != NULL) {
+ index_prev[i] = index[i];
+ }
}
BLI_LINKSTACK_SWAP(queue, queue_next);
@@ -2112,9 +2134,14 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float
BLI_LINKSTACK_FREE(queue_next);
MEM_freeN(dists_prev);
+ if (index_prev != NULL) {
+ MEM_freeN(index_prev);
+ }
}
-static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map)
+static struct TransIslandData *editmesh_islands_info_calc(
+ BMEditMesh *em, int *r_island_tot, int **r_island_vert_map,
+ bool calc_single_islands)
{
BMesh *bm = em->bm;
struct TransIslandData *trans_islands;
@@ -2226,6 +2253,42 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r
MEM_freeN(groups_array);
MEM_freeN(group_index);
+ /* for PET we need islands of 1 so connected vertices can use it with V3D_AROUND_LOCAL_ORIGINS */
+ if (calc_single_islands) {
+ BMIter viter;
+ BMVert *v;
+ int group_tot_single = 0;
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ group_tot_single += 1;
+ }
+ }
+
+ if (group_tot_single != 0) {
+ trans_islands = MEM_reallocN(trans_islands, group_tot + group_tot_single);
+
+ BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) {
+ if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) {
+ struct TransIslandData *v_island = &trans_islands[group_tot];
+ vert_map[i] = group_tot;
+
+ copy_v3_v3(v_island->co, v->co);
+
+ if (is_zero_v3(v->no) != 0.0f) {
+ axis_dominant_v3_to_m3(v_island->axismtx, v->no);
+ invert_m3(v_island->axismtx);
+ }
+ else {
+ unit_m3(v_island->axismtx);
+ }
+
+ group_tot += 1;
+ }
+ }
+ }
+ }
+
*r_island_tot = group_tot;
*r_island_vert_map = vert_map;
@@ -2325,6 +2388,11 @@ static void createTransEditVerts(TransInfo *t)
int island_info_tot;
int *island_vert_map = NULL;
+ const bool is_island_center = (t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION);
+ /* Original index of our connected vertex when connected distances are calculated.
+ * Optional, allocate if needed. */
+ int *dists_index = NULL;
+
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology);
mirror = 1;
@@ -2356,8 +2424,12 @@ static void createTransEditVerts(TransInfo *t)
t->total = count;
/* allocating scratch arrays */
- if (prop_mode & T_PROP_CONNECTED)
- dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears");
+ if (prop_mode & T_PROP_CONNECTED) {
+ dists = MEM_mallocN(em->bm->totvert * sizeof(float), __func__);
+ if (is_island_center) {
+ dists_index = MEM_mallocN(em->bm->totvert * sizeof(int), __func__);
+ }
+ }
}
else {
t->total = bm->totvertsel;
@@ -2379,7 +2451,7 @@ static void createTransEditVerts(TransInfo *t)
pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON);
if (prop_mode & T_PROP_CONNECTED) {
- editmesh_set_connectivity_distance(em->bm, mtx, dists);
+ editmesh_set_connectivity_distance(em->bm, mtx, dists, dists_index);
}
/* Only in case of rotation and resize, we want the elements of the edited
@@ -2387,8 +2459,14 @@ static void createTransEditVerts(TransInfo *t)
*
* TODO: use island_info to detect the closest point when the "Snap Target"
* in Blender UI is "Closest" */
- if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && (t->mode != TFM_TRANSLATION)) {
- island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map);
+ if (is_island_center) {
+ /* In this specific case, near-by vertices will need to know the island of the nearest connected vertex. */
+ const bool calc_single_islands = (
+ (prop_mode & T_PROP_CONNECTED) &&
+ (t->around == V3D_AROUND_LOCAL_ORIGINS) &&
+ (em->selectmode & SCE_SELECT_VERTEX));
+
+ island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map, calc_single_islands);
}
/* detect CrazySpace [tm] */
@@ -2438,10 +2516,16 @@ static void createTransEditVerts(TransInfo *t)
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
- struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ?
- &island_info[island_vert_map[a]] : NULL;
+ struct TransIslandData *v_island = NULL;
float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL;
+ if (island_info) {
+ const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a;
+ v_island = (island_vert_map[connected_index] != -1) ?
+ &island_info[island_vert_map[connected_index]] : NULL;
+ }
+
+
VertsToTransData(t, tob, tx, em, eve, bweight, v_island);
if (tx)
tx++;
@@ -2520,6 +2604,8 @@ cleanup:
MEM_freeN(defmats);
if (dists)
MEM_freeN(dists);
+ if (dists_index)
+ MEM_freeN(dists_index);
if (t->flag & T_MIRROR) {
EDBM_verts_mirror_cache_end(em);
@@ -5523,7 +5609,7 @@ static void clear_trans_object_base_flags(TransInfo *t)
* tmode: should be a transform mode
*/
// NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases
-void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode)
+void autokeyframe_ob_cb_func(bContext *C, Scene *scene, SceneLayer *sl, View3D *v3d, Object *ob, int tmode)
{
ID *id = &ob->id;
FCurve *fcu;
@@ -5572,7 +5658,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
}
else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) {
if (v3d->around == V3D_AROUND_ACTIVE) {
- if (ob != OBACT)
+ if (ob != OBACT_NEW)
do_loc = true;
}
else if (v3d->around == V3D_AROUND_CURSOR)
@@ -5583,7 +5669,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob,
}
else if (tmode == TFM_RESIZE) {
if (v3d->around == V3D_AROUND_ACTIVE) {
- if (ob != OBACT)
+ if (ob != OBACT_NEW)
do_loc = true;
}
else if (v3d->around == V3D_AROUND_CURSOR)
@@ -6302,10 +6388,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->options & CTX_PAINT_CURVE) {
/* pass */
}
- else if ((t->scene->basact) &&
- (ob = t->scene->basact->object) &&
+ else if ((t->sl->basact) &&
+ (ob = t->sl->basact->object) &&
(ob->mode & OB_MODE_PARTICLE_EDIT) &&
- PE_get_current(t->scene, ob))
+ PE_get_current(t->scene, t->sl, ob))
{
/* do nothing */
}
@@ -6346,7 +6432,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
/* Set autokey if necessary */
if (!canceled) {
- autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode);
+ autokeyframe_ob_cb_func(C, t->scene, t->sl, (View3D *)t->view, ob, t->mode);
}
/* restore rigid body transform */
@@ -6381,8 +6467,6 @@ int special_transform_moving(TransInfo *t)
static void createTransObject(bContext *C, TransInfo *t)
{
- Scene *scene = t->scene;
-
TransData *td = NULL;
TransDataExtension *tx;
const bool is_prop_edit = (t->flag & T_PROP_EDIT) != 0;
@@ -6432,15 +6516,16 @@ static void createTransObject(bContext *C, TransInfo *t)
CTX_DATA_END;
if (is_prop_edit) {
- View3D *v3d = t->view;
- BaseLegacy *base;
+ SceneLayer *sl = t->sl;
+ Base *base;
- for (base = scene->base.first; base; base = base->next) {
+ for (base = sl->object_bases.first; base; base = base->next) {
Object *ob = base->object;
/* if base is not selected, not a parent of selection or not a child of selection and it is editable */
- if ((ob->flag & (SELECT | BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
- BASE_EDITABLE_BGMODE(v3d, scene, base))
+ if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
+ (base->flag & BASE_SELECTED) == 0 &&
+ BASE_EDITABLE_BGMODE_NEW(base))
{
td->protectflag = ob->protectflag;
td->ext = tx;
@@ -8021,7 +8106,12 @@ void createTransData(bContext *C, TransInfo *t)
if (t->data && t->flag & T_PROP_EDIT) {
if (ELEM(t->obedit->type, OB_CURVE, OB_MESH)) {
sort_trans_data(t); // makes selected become first in array
- set_prop_dist(t, 0);
+ if ((t->obedit->type == OB_MESH) && (t->flag & T_PROP_CONNECTED)) {
+ /* already calculated by editmesh_set_connectivity_distance */
+ }
+ else {
+ set_prop_dist(t, 0);
+ }
sort_trans_data_dist(t);
}
else {
@@ -8057,7 +8147,7 @@ void createTransData(bContext *C, TransInfo *t)
}
}
- else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, ob))) {
+ else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT) && PE_start_edit(PE_get_current(scene, sl, ob))) {
createTransParticleVerts(C, t);
t->flag |= T_POINTS;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 2c10ee61466..6da0631ffa3 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -63,6 +63,7 @@
#include "RNA_access.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "BIK_api.h"
@@ -325,6 +326,7 @@ static void recalcData_actedit(TransInfo *t)
/* initialize relevant anim-context 'context' data from TransInfo data */
/* NOTE: sync this with the code in ANIM_animdata_get_context() */
ac.scene = t->scene;
+ ac.scene_layer = t->sl;
ac.obact = OBACT_NEW;
ac.sa = t->sa;
ac.ar = t->ar;
@@ -374,6 +376,7 @@ static void recalcData_graphedit(TransInfo *t)
/* initialize relevant anim-context 'context' data from TransInfo data */
/* NOTE: sync this with the code in ANIM_animdata_get_context() */
ac.scene = t->scene;
+ ac.scene_layer = t->sl;
ac.obact = OBACT_NEW;
ac.sa = t->sa;
ac.ar = t->ar;
@@ -708,7 +711,7 @@ static void recalcData_spaceclip(TransInfo *t)
/* helper for recalcData() - for object transforms, typically in the 3D view */
static void recalcData_objects(TransInfo *t)
{
- BaseLegacy *base = t->scene->basact;
+ Base *base = t->sl->basact;
if (t->obedit) {
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
@@ -895,7 +898,7 @@ static void recalcData_objects(TransInfo *t)
else
BKE_pose_where_is(t->scene, ob);
}
- else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, base->object)) {
+ else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) && PE_get_current(t->scene, t->sl, base->object)) {
if (t->state != TRANS_CANCEL) {
applyProject(t);
}
@@ -925,7 +928,7 @@ static void recalcData_objects(TransInfo *t)
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
animrecord_check_state(t->scene, &ob->id, t->animtimer);
- autokeyframe_ob_cb_func(t->context, t->scene, (View3D *)t->view, ob, t->mode);
+ autokeyframe_ob_cb_func(t->context, t->scene, t->sl, (View3D *)t->view, ob, t->mode);
}
/* sets recalc flags fully, instead of flushing existing ones
@@ -1031,11 +1034,10 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
if (t->spacetype == SPACE_VIEW3D) {
View3D *v3d = t->view;
- glPushMatrix();
-
- //if (t->obedit) glLoadMatrixf(t->obedit->obmat); // sets opengl viewing
-
-
+ gpuPushMatrix();
+
+ // if (t->obedit) gpuLoadMatrix3D(t->obedit->obmat); // sets opengl viewing
+
copy_v3_v3(v3, dir);
mul_v3_fl(v3, v3d->far);
@@ -1062,7 +1064,7 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
immUnbindProgram();
- glPopMatrix();
+ gpuPopMatrix();
}
}
@@ -1785,7 +1787,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
}
}
else if (t->options & CTX_PAINT_CURVE) {
- Paint *p = BKE_paint_get_active(t->scene);
+ Paint *p = BKE_paint_get_active(t->scene, t->sl);
Brush *br = p->brush;
PaintCurve *pc = br->paint_curve;
copy_v3_v3(r_center, pc->points[pc->add_index - 1].bez.vec[1]);
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index fed1b2f5676..1be477fb998 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -569,6 +569,9 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
// Add confirm method all the time. At the end because it's not really that important and should be hidden only in log, not in keymap edit
/*prop =*/ RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button");
//RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation");
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
prop = RNA_def_boolean(ot->srna, "draw_helplines", 1, "Draw Helplines", "");
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index bd640463da2..8f37b35c6f0 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -206,35 +206,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
else if (t->spacetype == SPACE_IMAGE) {
if (validSnap(t)) {
/* This will not draw, and Im nor sure why - campbell */
-#if 0
- float xuser_asp, yuser_asp;
- int wi, hi;
- float w, h;
-
- calc_image_view(G.sima, 'f'); // float
- myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
- glLoadIdentity();
-
- ED_space_image_get_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp);
- ED_space_image_width(t->sa->spacedata.first, &wi, &hi);
- w = (((float)wi) / IMG_SIZE_FALLBACK) * G.sima->zoom * xuser_asp;
- h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp;
-
- cpack(0xFFFFFF);
- glTranslate2fv(t->tsnap.snapPoint);
-
- //glRectf(0, 0, 1, 1);
-
- setlinestyle(0);
- cpack(0x0);
- fdrawline(-0.020 / w, 0, -0.1 / w, 0);
- fdrawline(0.1 / w, 0, 0.020 / w, 0);
- fdrawline(0, -0.020 / h, 0, -0.1 / h);
- fdrawline(0, 0.1 / h, 0, 0.020 / h);
-
- glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
- setlinestyle(0);
-#endif
+ /* TODO: see 2.7x for non-working code */
}
}
else if (t->spacetype == SPACE_NODE) {
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 2e95b67d508..587a62d017d 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -87,6 +87,8 @@ typedef struct SnapObjectData {
typedef struct SnapObjectData_Mesh {
SnapObjectData sd;
BVHTreeFromMesh *bvh_trees[3];
+ MPoly *mpoly;
+ bool poly_allocated;
} SnapObjectData_Mesh;
@@ -934,9 +936,10 @@ static bool snapEmpty(
float tmp_co[3];
copy_v3_v3(tmp_co, obmat[3]);
if (test_projected_vert_dist(
- snapdata->depth_range, snapdata->mval, tmp_co,
- snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
- r_loc)) {
+ snapdata->depth_range, snapdata->mval, tmp_co,
+ snapdata->pmat, snapdata->win_half, is_persp, &dist_px_sq,
+ r_loc))
+ {
*dist_px = sqrtf(dist_px_sq);
*ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
@@ -1051,7 +1054,6 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
static bool snapDerivedMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index,
- bool do_bb,
/* read/write args */
float *ray_depth, float *dist_px,
/* return args */
@@ -1112,39 +1114,30 @@ static bool snapDerivedMesh(
copy_v3_v3(ray_org_local, snapdata->ray_origin);
mul_m4_v3(imat, ray_org_local);
- if (do_bb) {
- BoundBox *bb = BKE_object_boundbox_get(ob);
-
- if (bb) {
- BoundBox bb_temp;
-
- /* We cannot afford a bounding box with some null dimension, which may happen in some cases...
- * Threshold is rather high, but seems to be needed to get good behavior, see T46099. */
- bb = BKE_boundbox_ensure_minimum_dimensions(bb, &bb_temp, 1e-1f);
-
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see T46816. */
- if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
- float dist_px_sq = dist_squared_to_projected_aabb_simple(
- lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
- ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
- if (dist_px_sq > SQUARE(*dist_px))
- {
- return retval;
- }
+ /* Test BoundBox */
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ if (bb) {
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ if (ELEM(snapdata->snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
+ float dist_px_sq = dist_squared_to_projected_aabb_simple(
+ lpmat, snapdata->win_half, ray_min_dist, snapdata->mval,
+ ray_org_local, ray_normal_local, bb->vec[0], bb->vec[6]);
+ if (dist_px_sq > SQUARE(*dist_px)) {
+ return retval;
}
- else {
- /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
- if (!isect_ray_aabb_v3_simple(
- ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
- {
- return retval;
- }
+ }
+ else {
+ /* was BKE_boundbox_ray_hit_check, see: cf6ca226fa58 */
+ if (!isect_ray_aabb_v3_simple(
+ ray_start_local, ray_normal_local, bb->vec[0], bb->vec[6], NULL, NULL))
+ {
+ return retval;
}
- /* was local_depth, see: T47838 */
- len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
- if (len_diff < 0) len_diff = 0.0f;
- need_ray_start_correction_init = false;
}
+ /* was local_depth, see: T47838 */
+ len_diff = dist_aabb_to_plane(bb->vec[0], bb->vec[6], ray_start_local, ray_normal_local);
+ if (len_diff < 0) len_diff = 0.0f;
+ need_ray_start_correction_init = false;
}
SnapObjectData_Mesh *sod = NULL;
@@ -1182,6 +1175,29 @@ static bool snapDerivedMesh(
if (treedata->cached && !bvhcache_has_tree(dm->bvhCache, treedata->tree)) {
free_bvhtree_from_mesh(treedata);
}
+ else {
+ if (!treedata->vert_allocated) {
+ treedata->vert = DM_get_vert_array(dm, &treedata->vert_allocated);
+ }
+ if ((tree_index == 1) && !treedata->edge_allocated) {
+ treedata->edge = DM_get_edge_array(dm, &treedata->vert_allocated);
+ }
+ if (tree_index == 2) {
+ if (!treedata->loop_allocated) {
+ treedata->loop = DM_get_loop_array(dm, &treedata->loop_allocated);
+ }
+ if (!treedata->looptri_allocated) {
+ if (!sod->poly_allocated) {
+ sod->mpoly = DM_get_poly_array(dm, &sod->poly_allocated);
+ }
+ treedata->looptri = DM_get_looptri_array(
+ dm, treedata->vert,
+ sod->mpoly, dm->getNumPolys(dm),
+ treedata->loop, dm->getNumLoops(dm),
+ &treedata->looptri_allocated);
+ }
+ }
+ }
}
}
@@ -1295,10 +1311,17 @@ static bool snapDerivedMesh(
}
/* SCE_SNAP_MODE_VERTEX or SCE_SNAP_MODE_EDGE */
else {
+
+ /* Warning: the depth_max is currently being used only in perspective view.
+ * It is not correct to limit the maximum depth for elements obtained with nearest
+ * since this limitation depends on the normal and the size of the occlusion face.
+ * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
+ const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
+
Nearest2dUserData neasrest2d = {
.dist_px_sq = SQUARE(*dist_px),
.r_axis_closest = {1.0f, 1.0f, 1.0f},
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
+ .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
.userdata = treedata,
.get_edge_verts = (Nearest2DGetEdgeVertsCallback)get_dm_edge_verts,
.copy_vert_no = (Nearest2DCopyVertNoCallback)copy_dm_vert_no,
@@ -1650,7 +1673,6 @@ static bool snapObject(
}
retval = snapDerivedMesh(
sctx, snapdata, ob, dm, obmat, ob_index,
- true,
ray_depth, dist_px,
r_loc, r_no,
r_index, r_hit_list);
@@ -1858,6 +1880,9 @@ static void snap_object_data_free(void *sod_v)
free_bvhtree_from_mesh(sod->bvh_trees[i]);
}
}
+ if (sod->poly_allocated) {
+ MEM_freeN(sod->mpoly);
+ }
break;
}
case SNAP_EDIT_MESH:
@@ -2053,10 +2078,10 @@ static bool transform_snap_context_project_view3d_mixed_impl(
for (int i = 0; i < 3; i++) {
if (snap_to_flag & (1 << i)) {
if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
+ sctx,
+ elem_type[i], params,
+ mval, dist_px, &ray_depth,
+ r_co, r_no))
{
is_hit = true;
break;
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index 482523e56be..96864c88d9d 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -88,7 +88,8 @@ void ED_editors_init(bContext *C)
wmWindowManager *wm = CTX_wm_manager(C);
Main *bmain = CTX_data_main(C);
Scene *sce = CTX_data_scene(C);
- Object *ob, *obact = (sce && sce->basact) ? sce->basact->object : NULL;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob, *obact = (sl && sl->basact) ? sl->basact->object : NULL;
ID *data;
/* This is called during initialization, so we don't want to store any reports */
diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c
index e07831358d6..3727be1842c 100644
--- a/source/blender/editors/util/numinput.c
+++ b/source/blender/editors/util/numinput.c
@@ -497,7 +497,7 @@ bool handleNumInput(bContext *C, NumInput *n, const wmEvent *event)
n->unit_sys, n->unit_type[idx]);
/* Note: with angles, we always get values as radians here... */
- if (BPY_execute_string_as_number(C, str_unit_convert, &val, false)) {
+ if (BPY_execute_string_as_number(C, str_unit_convert, false, &val)) {
n->val[idx] = (float)val;
n->val_flag[idx] &= ~NUM_INVALID;
}
diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c
index fab5b7e821f..f5830e451e3 100644
--- a/source/blender/editors/util/undo.c
+++ b/source/blender/editors/util/undo.c
@@ -101,7 +101,7 @@ void ED_undo_push(bContext *C, const char *str)
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (U.undosteps == 0) return;
- PE_undo_push(CTX_data_scene(C), str);
+ PE_undo_push(CTX_data_scene(C), CTX_data_scene_layer(C), str);
}
else if (obact && obact->mode & OB_MODE_SCULPT) {
/* do nothing for now */
@@ -120,6 +120,7 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
wmWindow *win = CTX_wm_window(C);
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
+ SceneLayer *sl = CTX_data_scene_layer(C);
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
ScrArea *sa = CTX_wm_area(C);
@@ -180,9 +181,9 @@ static int ed_undo_step(bContext *C, int step, const char *undoname)
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
if (step == 1)
- PE_undo(scene);
+ PE_undo(scene, sl);
else
- PE_redo(scene);
+ PE_redo(scene, sl);
}
else if (U.uiflag & USER_GLOBALUNDO) {
// note python defines not valid here anymore.
@@ -297,7 +298,7 @@ bool ED_undo_is_valid(const bContext *C, const char *undoname)
return 1;
}
else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {
- return PE_undo_is_valid(CTX_data_scene(C));
+ return PE_undo_is_valid(CTX_data_scene(C), CTX_data_scene_layer(C));
}
if (U.uiflag & USER_GLOBALUNDO) {
@@ -419,6 +420,9 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op)
if (G.debug & G_DEBUG)
printf("redo_cb: operator redo %s\n", op->type->name);
+
+ WM_operator_free_all_after(wm, op);
+
ED_undo_pop_op(C, op);
if (op->type->check) {
@@ -533,7 +537,7 @@ static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem)
const char *name = NULL;
if (undosys == UNDOSYSTEM_PARTICLE) {
- name = PE_undo_get_name(CTX_data_scene(C), i, &active);
+ name = PE_undo_get_name(CTX_data_scene(C), CTX_data_scene_layer(C), i, &active);
}
else if (undosys == UNDOSYSTEM_EDITMODE) {
name = undo_editmode_get_name(C, i, &active);
@@ -616,7 +620,7 @@ static int undo_history_exec(bContext *C, wmOperator *op)
int item = RNA_int_get(op->ptr, "item");
if (undosys == UNDOSYSTEM_PARTICLE) {
- PE_undo_number(CTX_data_scene(C), item);
+ PE_undo_number(CTX_data_scene(C), CTX_data_scene_layer(C), item);
}
else if (undosys == UNDOSYSTEM_EDITMODE) {
undo_editmode_number(C, item + 1);
diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt
index 543ef0e0663..a933717fe98 100644
--- a/source/blender/editors/uvedit/CMakeLists.txt
+++ b/source/blender/editors/uvedit/CMakeLists.txt
@@ -24,6 +24,7 @@ set(INC
../../blenlib
../../blentranslation
../../bmesh
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index 3510e1e7088..d8654b9d18a 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -46,16 +46,19 @@
#include "BLI_buffer.h"
#include "BLI_bitmap.h"
+#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_editmesh.h"
#include "BKE_material.h"
#include "BKE_scene.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "DEG_depsgraph.h"
+
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "ED_image.h"
#include "ED_mesh.h"
@@ -67,11 +70,6 @@
#include "uvedit_intern.h"
-#include "GPU_basic_shader.h"
-
-/* use editmesh tessface */
-#define USE_EDBM_LOOPTRIS
-
static void draw_uvs_lineloop_bmface(BMFace *efa, const int cd_loop_uv_offset, unsigned int pos);
void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
@@ -84,7 +82,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
x_fac = zoom[0];
y_fac = zoom[1];
- glTranslate2fv(cursor);
+ gpuTranslate2fv(cursor);
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
@@ -145,7 +143,7 @@ void ED_image_draw_cursor(ARegion *ar, const float cursor[2])
immUnbindProgram();
- glTranslatef(-cursor[0], -cursor[1], 0.0);
+ gpuTranslate2f(-cursor[0], -cursor[1]);
setlinestyle(0);
}
@@ -189,19 +187,6 @@ static void draw_uvs_shadow(Object *obedit)
immUnbindProgram();
}
-static int draw_uvs_dm_shadow(DerivedMesh *dm)
-{
- /* draw shadow mesh - this is the mesh with the modifier applied */
-
- if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) {
- UI_ThemeColor(TH_UV_SHADOW);
- dm->drawUVEdges(dm);
- return 1;
- }
-
- return 0;
-}
-
static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTexPoly *activetf)
{
BMesh *bm = em->bm;
@@ -304,7 +289,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
weight_to_rgb(col, areadiff);
immUniformColor3fv(col);
- /* TODO: USE_EDBM_LOOPTRIS */
+ /* TODO: use editmesh tessface */
immBegin(GL_TRIANGLE_FAN, efa->len);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -332,7 +317,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
col[3] = 0.5f; /* hard coded alpha, not that nice */
- VertexFormat* format = immVertexFormat();
+ VertexFormat *format = immVertexFormat();
unsigned int pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned int color = add_attrib(format, "color", GL_FLOAT, 3, KEEP_FLOAT);
@@ -378,7 +363,7 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe
ang[i] = angle_normalized_v3v3(av[i], av[(i + 1) % efa_len]);
}
- /* TODO: USE_EDBM_LOOPTRIS */
+ /* TODO: use editmesh tessface */
immBegin(GL_TRIANGLE_FAN, efa->len);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -532,33 +517,29 @@ static void draw_uvs_other_mesh(Object *ob, const Image *curimage, const bool ne
}
}
-static void draw_uvs_other(Scene *scene, Object *obedit, const Image *curimage, const bool new_shading_nodes,
+static void draw_uvs_other(SceneLayer *sl, Object *obedit, const Image *curimage, const bool new_shading_nodes,
const int other_uv_filter)
{
- BaseLegacy *base;
-
unsigned int pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
immUniformThemeColor(TH_UV_OTHERS);
- for (base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
- if (!(base->flag_legacy & SELECT)) continue;
- if (!(base->lay & scene->lay)) continue;
- if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
-
- if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
- draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter, pos);
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if (((base->flag & BASE_SELECTED) != 0) &&
+ ((base->flag & BASE_VISIBLED) != 0))
+ {
+ Object *ob = base->object;
+ if ((ob->type == OB_MESH) && (ob != obedit) && ((Mesh *)ob->data)->mloopuv) {
+ draw_uvs_other_mesh(ob, curimage, new_shading_nodes, other_uv_filter, pos);
+ }
}
}
-
immUnbindProgram();
}
-static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
+static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, SceneLayer *sl, Object *ob)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
Image *curimage = ED_space_image(sima);
@@ -566,7 +547,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
Material *ma;
if (sima->flag & SI_DRAW_OTHER) {
- draw_uvs_other(scene, ob, curimage, new_shading_nodes, sima->other_uv_filter);
+ draw_uvs_other(sl, ob, curimage, new_shading_nodes, sima->other_uv_filter);
}
ma = give_current_material(ob, ob->actcol);
@@ -607,7 +588,6 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob)
}
}
-#ifdef USE_EDBM_LOOPTRIS
static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const int cd_loop_uv_offset, unsigned int pos)
{
unsigned int i = *r_loop_index;
@@ -622,10 +602,9 @@ static void draw_uvs_looptri(BMEditMesh *em, unsigned int *r_loop_index, const i
} while (i != em->tottri && (f == em->looptris[i][0]->f));
*r_loop_index = i - 1;
}
-#endif
/* draws uv's in the image space */
-static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
+static void draw_uvs(SpaceImage *sima, Scene *scene, SceneLayer *sl, Object *obedit, Depsgraph *depsgraph)
{
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
ToolSettings *ts;
@@ -633,14 +612,10 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
BMEditMesh *em = me->edit_btmesh;
BMesh *bm = em->bm;
BMFace *efa, *efa_act;
-#ifndef USE_EDBM_LOOPTRIS
- BMFace *activef;
-#endif
BMLoop *l;
BMIter iter, liter;
MTexPoly *tf, *activetf = NULL;
MLoopUV *luv;
- DerivedMesh *finaldm, *cagedm;
unsigned char col1[4], col2[4];
float pointsize;
int drawfaces, interpedges;
@@ -652,9 +627,6 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
unsigned int pos;
activetf = EDBM_mtexpoly_active_get(em, &efa_act, false, false); /* will be set to NULL if hidden */
-#ifndef USE_EDBM_LOOPTRIS
- activef = BM_mesh_active_face_get(bm, false, false);
-#endif
ts = scene->toolsettings;
drawfaces = draw_uvs_face_check(scene);
@@ -679,28 +651,20 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
curimage = (activetf) ? activetf->tpage : ima;
}
- draw_uvs_other(scene, obedit, curimage, new_shading_nodes, sima->other_uv_filter);
+ draw_uvs_other(sl, obedit, curimage, new_shading_nodes, sima->other_uv_filter);
}
/* 1. draw shadow mesh */
if (sima->flag & SI_DRAWSHADOW) {
- DM_update_materials(em->derivedFinal, obedit);
- /* first try existing derivedmesh */
- if (!draw_uvs_dm_shadow(em->derivedFinal)) {
- /* create one if it does not exist */
- cagedm = editbmesh_get_derived_cage_and_final(
- scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH | CD_MASK_MTFACE,
- &finaldm);
-
- /* when sync selection is enabled, all faces are drawn (except for hidden)
- * so if cage is the same as the final, theres no point in drawing this */
- if (!((ts->uv_flag & UV_SYNC_SELECTION) && (cagedm == finaldm)))
- draw_uvs_dm_shadow(finaldm);
-
- /* release derivedmesh again */
- if (cagedm != finaldm) cagedm->release(cagedm);
- finaldm->release(finaldm);
+ Object *ob_cage = DAG_get_object(depsgraph, obedit);
+ /* XXX TODO: Need to check if shadow mesh is different than original mesh. */
+ bool is_cage_like_final_meshes = (ob_cage == obedit);
+
+ /* When sync selection is enabled, all faces are drawn (except for hidden)
+ * so if cage is the same as the final, there is no point in drawing this. */
+ if (((ts->uv_flag & UV_SYNC_SELECTION) == 0) || is_cage_like_final_meshes) {
+ draw_uvs_shadow(ob_cage);
}
}
@@ -716,66 +680,36 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
-#ifdef USE_EDBM_LOOPTRIS
- {
- unsigned int i;
-
- pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
-
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
-
- for (i = 0; i < em->tottri; i++) {
- efa = em->looptris[i][0]->f;
- tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, efa, tf)) {
- const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
- BM_elem_flag_enable(efa, BM_ELEM_TAG);
-
- if (tf == activetf) {
- /* only once */
- immUniformThemeColor(TH_EDITMESH_ACTIVE);
- }
- else {
- immUniformColor4ubv(is_select ? col2 : col1);
- }
+ pos = add_attrib(immVertexFormat(), "pos", GL_FLOAT, 2, KEEP_FLOAT);
- immBegin(GL_TRIANGLES, (em->looptris[i][0]->f->len - 2) * 3);
- draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
- immEnd();
- }
- else {
- BM_elem_flag_disable(efa, BM_ELEM_TAG);
- }
- }
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUnbindProgram();
- }
-#else
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
+ for (unsigned int i = 0; i < em->tottri; i++) {
+ efa = em->looptris[i][0]->f;
tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
if (uvedit_face_visible_test(scene, ima, efa, tf)) {
+ const bool is_select = uvedit_face_select_test(scene, efa, cd_loop_uv_offset);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
- if (tf == activetf) continue; /* important the temp boolean is set above */
- if (uvedit_face_select_test(scene, efa, cd_loop_uv_offset))
- glColor4ubv((GLubyte *)col2);
- else
- glColor4ubv((GLubyte *)col1);
-
- glBegin(GL_POLYGON);
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
+ if (tf == activetf) {
+ /* only once */
+ immUniformThemeColor(TH_EDITMESH_ACTIVE);
}
- glEnd();
+ else {
+ immUniformColor4ubv(is_select ? col2 : col1);
+ }
+
+ immBegin(GL_TRIANGLES, (em->looptris[i][0]->f->len - 2) * 3);
+ draw_uvs_looptri(em, &i, cd_loop_uv_offset, pos);
+ immEnd();
}
else {
- if (tf == activetf)
- activetf = NULL;
BM_elem_flag_disable(efa, BM_ELEM_TAG);
}
}
-#endif
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
}
else {
@@ -797,30 +731,8 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
}
/* 3. draw active face stippled */
-#ifndef USE_EDBM_LOOPTRIS
- if (activef) {
- tf = BM_ELEM_CD_GET_VOID_P(activef, cd_poly_tex_offset);
- if (uvedit_face_visible_test(scene, ima, activef, tf)) {
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- UI_ThemeColor4(TH_EDITMESH_ACTIVE);
-
- GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE);
-
- glBegin(GL_POLYGON);
- BM_ITER_ELEM (l, &liter, activef, BM_LOOPS_OF_FACE) {
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- glVertex2fv(luv->uv);
- }
- glEnd();
+ /* (removed during OpenGL upgrade, reimplement if needed) */
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glDisable(GL_BLEND);
- }
- }
-#endif
-
/* 4. draw edges */
if (sima->flag & SI_SMOOTH_UV) {
@@ -906,7 +818,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
int sel;
UI_GetThemeColor4ubv(TH_EDGE_SELECT, col1);
- VertexFormat* format = immVertexFormat();
+ VertexFormat *format = immVertexFormat();
pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 4, NORMALIZE_INT_TO_FLOAT);
@@ -993,7 +905,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit)
float cent[2];
bool col_set = false;
- VertexFormat* format = immVertexFormat();
+ VertexFormat *format = immVertexFormat();
pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
unsigned int color = add_attrib(format, "color", GL_UNSIGNED_BYTE, 3, NORMALIZE_INT_TO_FLOAT);
@@ -1140,7 +1052,7 @@ static void draw_uv_shadows_get(SpaceImage *sima, Object *ob, Object *obedit, bo
*show_texpaint = (ob && ob->type == OB_MESH && ob->mode == OB_MODE_TEXTURE_PAINT);
}
-void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedit, Object *obact)
+void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, SceneLayer *sl, Object *obedit, Object *obact, Depsgraph *depsgraph)
{
ToolSettings *toolsettings = scene->toolsettings;
bool show_uvedit, show_uvshadow, show_texpaint_uvshadow;
@@ -1152,9 +1064,9 @@ void ED_uvedit_draw_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *ob
if (show_uvshadow)
draw_uvs_shadow(obedit);
else if (show_uvedit)
- draw_uvs(sima, scene, obedit);
+ draw_uvs(sima, scene, sl, obedit, depsgraph);
else
- draw_uvs_texpaint(sima, scene, obact);
+ draw_uvs_texpaint(sima, scene, sl, obact);
if (show_uvedit && !(toolsettings->use_uv_sculpt))
ED_image_draw_cursor(ar, sima->cursor);
diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c
index 50aec737c8e..014aa65efb5 100644
--- a/source/blender/editors/uvedit/uvedit_smart_stitch.c
+++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c
@@ -63,6 +63,8 @@
#include "ED_screen.h"
#include "ED_space_api.h"
+#include "GPU_batch.h"
+
#include "RNA_access.h"
#include "RNA_define.h"
@@ -1538,63 +1540,118 @@ static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *no
normalize_v2(normal);
}
+static void stitch_draw_vbo(VertexBuffer *vbo, int type, const float col[4])
+{
+ Batch *batch = Batch_create(type, vbo, NULL);
+ Batch_set_builtin_program(batch, GPU_SHADER_2D_UNIFORM_COLOR);
+ Batch_Uniform4fv(batch, "color", col);
+ Batch_draw(batch);
+ Batch_discard_all(batch);
+}
+
+/* TODO make things pretier : store batches inside StitchPreviewer instead of the bare verts pos */
static void stitch_draw(const bContext *UNUSED(C), ARegion *UNUSED(ar), void *arg)
{
- int i, index = 0;
+ int j, index = 0;
+ unsigned int num_line = 0, num_tri, tri_idx = 0, line_idx = 0;
StitchState *state = (StitchState *)arg;
StitchPreviewer *stitch_preview = state->stitch_preview;
+ VertexBuffer *vbo, *vbo_line;
+ float col[4];
- glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
- glEnableClientState(GL_VERTEX_ARRAY);
+ static VertexFormat format = { 0 };
+ static unsigned pos_id;
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ }
glEnable(GL_BLEND);
- UI_ThemeColor4(TH_STITCH_PREVIEW_ACTIVE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->static_tris);
- glDrawArrays(GL_TRIANGLES, 0, stitch_preview->num_static_tris * 3);
-
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_polys);
- for (i = 0; i < stitch_preview->num_polys; i++) {
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- UI_ThemeColor4(TH_STITCH_PREVIEW_FACE);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- UI_ThemeColor4(TH_STITCH_PREVIEW_EDGE);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
-#if 0
- glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
- UI_ThemeColor4(TH_STITCH_PREVIEW_VERT);
- glDrawArrays(GL_POLYGON, index, stitch_preview->uvs_per_polygon[i]);
-#endif
-
- index += stitch_preview->uvs_per_polygon[i];
+ /* Static Tris */
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_ACTIVE, col);
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, stitch_preview->num_static_tris * 3);
+ for (int i = 0; i < stitch_preview->num_static_tris * 3; i++)
+ setAttrib(vbo, pos_id, i, &stitch_preview->static_tris[i*2]);
+ stitch_draw_vbo(vbo, GL_TRIANGLES, col);
+
+
+ /* Preview Polys */
+ for (int i = 0; i < stitch_preview->num_polys; i++)
+ num_line += stitch_preview->uvs_per_polygon[i];
+
+ num_tri = num_line - 2 * stitch_preview->num_polys;
+
+ /* we need to convert the polys into triangles / lines */
+ vbo = VertexBuffer_create_with_format(&format);
+ vbo_line = VertexBuffer_create_with_format(&format);
+
+ VertexBuffer_allocate_data(vbo, num_tri * 3);
+ VertexBuffer_allocate_data(vbo_line, num_line * 2);
+
+ for (int i = 0; i < stitch_preview->num_polys; i++) {
+ BLI_assert(stitch_preview->uvs_per_polygon[i] >= 3);
+
+ /* Start line */
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + 2]);
+
+ for (j = 1; j < stitch_preview->uvs_per_polygon[i] - 1; ++j) {
+ setAttrib(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index]);
+ setAttrib(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j+0)*2]);
+ setAttrib(vbo, pos_id, tri_idx++, &stitch_preview->preview_polys[index + (j+1)*2]);
+
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j+0)*2]);
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + (j+1)*2]);
+ }
+
+ /* Closing line */
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index]);
+ setAttrib(vbo_line, pos_id, line_idx++, &stitch_preview->preview_polys[index + j*2]); /* j = uvs_per_polygon[i] - 1*/
+
+ index += stitch_preview->uvs_per_polygon[i] * 2;
}
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_FACE, col);
+ stitch_draw_vbo(vbo, GL_TRIANGLES, col);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_EDGE, col);
+ stitch_draw_vbo(vbo_line, GL_LINES, col);
+
glDisable(GL_BLEND);
- /* draw vert preview */
+
+ /* draw stitch vert/lines preview */
if (state->mode == STITCH_VERT) {
glPointSize(UI_GetThemeValuef(TH_VERTEX_SIZE) * 2.0f);
- UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_stitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, stitch_preview->num_stitchable);
+ for (int i = 0; i < stitch_preview->num_stitchable; i++)
+ setAttrib(vbo, pos_id, i, &stitch_preview->preview_stitchable[i*2]);
+ stitch_draw_vbo(vbo, GL_POINTS, col);
- UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
- glDrawArrays(GL_POINTS, 0, stitch_preview->num_unstitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, stitch_preview->num_unstitchable);
+ for (int i = 0; i < stitch_preview->num_unstitchable; i++)
+ setAttrib(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i*2]);
+ stitch_draw_vbo(vbo, GL_POINTS, col);
}
else {
- UI_ThemeColor4(TH_STITCH_PREVIEW_STITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_stitchable);
- glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_stitchable);
-
- UI_ThemeColor4(TH_STITCH_PREVIEW_UNSTITCHABLE);
- glVertexPointer(2, GL_FLOAT, 0, stitch_preview->preview_unstitchable);
- glDrawArrays(GL_LINES, 0, 2 * stitch_preview->num_unstitchable);
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_STITCHABLE, col);
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, stitch_preview->num_stitchable * 2);
+ for (int i = 0; i < stitch_preview->num_stitchable * 2; i++)
+ setAttrib(vbo, pos_id, i, &stitch_preview->preview_stitchable[i*2]);
+ stitch_draw_vbo(vbo, GL_LINES, col);
+
+ UI_GetThemeColor4fv(TH_STITCH_PREVIEW_UNSTITCHABLE, col);
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, stitch_preview->num_unstitchable * 2);
+ for (int i = 0; i < stitch_preview->num_unstitchable * 2; i++)
+ setAttrib(vbo, pos_id, i, &stitch_preview->preview_unstitchable[i*2]);
+ stitch_draw_vbo(vbo, GL_LINES, col);
}
-
- glPopClientAttrib();
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
static UvEdge *uv_edge_get(BMLoop *l, StitchState *state)
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
index 9c462bb6b2b..6f5491fc8ef 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.cpp
@@ -51,7 +51,6 @@ IndexedFaceSet::IndexedFaceSet() : Rep()
_MISize = 0;
_TIndices = NULL;
_TISize = 0;
- _displayList = 0;
}
IndexedFaceSet::IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormals, unsigned iNSize,
@@ -150,8 +149,6 @@ IndexedFaceSet::IndexedFaceSet(float *iVertices, unsigned iVSize, float *iNormal
_TISize = iTISize;
_TIndices = iTIndices;
}
-
- _displayList = 0;
}
IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
@@ -215,8 +212,6 @@ IndexedFaceSet::IndexedFaceSet(const IndexedFaceSet& iBrother) : Rep(iBrother)
_TIndices = new unsigned[_TISize];
memcpy(_TIndices, iBrother.tindices(), _TISize * sizeof(unsigned));
}
-
- _displayList = 0;
}
IndexedFaceSet::~IndexedFaceSet()
@@ -276,10 +271,6 @@ IndexedFaceSet::~IndexedFaceSet()
delete[] _TIndices;
_TIndices = NULL;
}
-
- // should find a way to deallocates the displayList
- // glDeleteLists(GLuint list, GLSizei range)
- _displayList = 0;
}
void IndexedFaceSet::accept(SceneVisitor& v)
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
index 8d7bf986bde..16dea6f907e 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -150,8 +150,6 @@ public:
std::swap(_MISize, ioOther._MISize);
std::swap(_TISize, ioOther._TISize);
- std::swap(_displayList, ioOther._displayList);
-
Rep::swap(ioOther);
}
@@ -173,12 +171,6 @@ public:
/*! Compute the Bounding Box */
virtual void ComputeBBox();
- /*! modifiers */
- inline void setDisplayList(unsigned int index)
- {
- _displayList = index;
- }
-
/*! Accessors */
virtual const float *vertices() const
{
@@ -280,11 +272,6 @@ public:
return _TISize;
}
- inline unsigned int displayList() const
- {
- return _displayList;
- }
-
protected:
float *_Vertices;
float *_Normals;
@@ -311,8 +298,6 @@ protected:
unsigned _MISize;
unsigned _TISize;
- unsigned int _displayList;
-
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:IndexedFaceSet")
#endif
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 7573985baa8..f0ef87c5f28 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -42,6 +42,7 @@ set(INC
../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
+ ../../../intern/gawain
)
set(INC_SYS
@@ -60,32 +61,17 @@ set(SRC
intern/gpu_framebuffer.c
intern/gpu_immediate.c
intern/gpu_init_exit.c
+ intern/gpu_lamp.c
intern/gpu_material.c
intern/gpu_matrix.c
intern/gpu_select.c
+ intern/gpu_select_pick.c
+ intern/gpu_select_sample_query.c
intern/gpu_shader.c
intern/gpu_texture.c
intern/gpu_uniformbuffer.c
intern/gpu_viewport.c
- gawain/attrib_binding.c
- gawain/attrib_binding.h
- gawain/batch.c
- gawain/batch.h
- gawain/buffer_id.h
- gawain/buffer_id.cpp
- gawain/common.h
- gawain/element.c
- gawain/element.h
- gawain/immediate.c
- gawain/immediate.h
- gawain/imm_util.c
- gawain/imm_util.h
- gawain/vertex_buffer.c
- gawain/vertex_buffer.h
- gawain/vertex_format.c
- gawain/vertex_format.h
-
shaders/gpu_shader_fx_lib.glsl
shaders/gpu_shader_fx_ssao_frag.glsl
shaders/gpu_shader_fx_dof_frag.glsl
@@ -93,7 +79,7 @@ set(SRC
shaders/gpu_shader_fx_dof_hq_frag.glsl
shaders/gpu_shader_fx_dof_hq_vert.glsl
shaders/gpu_shader_fx_dof_hq_geo.glsl
- shaders/gpu_shader_fx_vert.glsl
+ shaders/gpu_shader_fullscreen_vert.glsl
shaders/gpu_shader_material.glsl
shaders/gpu_shader_sep_gaussian_blur_frag.glsl
shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -129,19 +115,27 @@ set(SRC
intern/gpu_codegen.h
intern/gpu_private.h
+ intern/gpu_lamp_private.h
+ intern/gpu_select_private.h
+ intern/gpu_shader_private.h
)
data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
@@ -158,25 +152,31 @@ data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC)
@@ -205,7 +205,7 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fullscreen_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_basic_shader.h b/source/blender/gpu/GPU_basic_shader.h
index bfdf4ab6bbd..dc378927e79 100644
--- a/source/blender/gpu/GPU_basic_shader.h
+++ b/source/blender/gpu/GPU_basic_shader.h
@@ -126,9 +126,6 @@ void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id);
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern);
void GPU_basic_shader_line_width(float line_width);
-bool GPU_basic_shader_use_glsl_get(void);
-void GPU_basic_shader_use_glsl_set(bool enabled);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 066bc9eeba7..2232e333bb6 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -30,7 +30,11 @@
#pragma once
-#include "gawain/batch.h"
+#include "../../../intern/gawain/gawain/batch.h"
+
+// TODO: CMake magic to do this:
+// #include "gawain/batch.h"
+
#include "GPU_shader.h"
/* Extend Batch_set_program to use Blender’s library of built-in shader programs. */
@@ -38,6 +42,7 @@ void Batch_set_builtin_program(Batch*, GPUBuiltinShader);
/* Replacement for gluSphere */
Batch *Batch_get_sphere(int lod);
+Batch *Batch_get_sphere_wire(int lod);
void gpu_batch_init(void);
void gpu_batch_exit(void);
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index b693d473bd8..958d5aed4a4 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -258,10 +258,8 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **gr
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
bool wireframe, bool fast);
-/* debug PBVH draw*/
-void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf);
-void GPU_end_draw_pbvh_BB(void);
-void GPU_init_draw_pbvh_BB(void);
+/* debug PBVH draw */
+void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos);
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color);
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
index 921deaaa6d6..c7a99d33654 100644
--- a/source/blender/gpu/GPU_debug.h
+++ b/source/blender/gpu/GPU_debug.h
@@ -41,9 +41,6 @@ extern "C" {
/* prints something if debug mode is active only */
void GPU_print_error_debug(const char *str);
-/* prints current OpenGL state */
-void GPU_state_print(void);
-
/* inserts a debug marker message for the debug context messaging system */
void GPU_string_marker(const char *str);
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 91d436557f0..47ddabbed19 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -42,6 +42,7 @@ struct ImageUser;
struct MTexPoly;
struct Object;
struct Scene;
+struct SceneLayer;
struct View3D;
struct RegionView3D;
struct SmokeModifierData;
@@ -74,7 +75,8 @@ void GPU_disable_program_point_size(void);
* - after drawing, the material must be disabled again */
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
- struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
+ struct Scene *scene, struct SceneLayer *sl,
+ struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
bool GPU_object_materials_check(void);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 9611a6f0577..15617832c9b 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -67,6 +67,10 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, struct GPUTexture *tex,
GPUFrameBuffer *blurfb, struct GPUTexture *blurtex);
+void GPU_framebuffer_blit(
+ GPUFrameBuffer *fb_read, int read_slot,
+ GPUFrameBuffer *fb_write, int write_slot, bool use_depth);
+
/* GPU OffScreen
* - wrapper around framebuffer and texture for simple offscreen drawing
* - changes size if graphics card can't support it */
diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h
index 4a0840e22c0..35964a81030 100644
--- a/source/blender/gpu/GPU_immediate.h
+++ b/source/blender/gpu/GPU_immediate.h
@@ -30,8 +30,13 @@
#pragma once
-#include "gawain/immediate.h"
-#include "gawain/imm_util.h"
+#include "../../../intern/gawain/gawain/immediate.h"
+#include "../../../intern/gawain/gawain/imm_util.h"
+
+// TODO: CMake magic to do this:
+// #include "gawain/immediate.h"
+// #include "gawain/imm_util.h"
+
#include "GPU_shader.h"
/* Extend immBindProgram to use Blender’s library of built-in shader programs.
diff --git a/source/blender/gpu/GPU_lamp.h b/source/blender/gpu/GPU_lamp.h
new file mode 100644
index 00000000000..32793830479
--- /dev/null
+++ b/source/blender/gpu/GPU_lamp.h
@@ -0,0 +1,75 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_lamp.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_H__
+#define __GPU_LAMP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Scene;
+struct Object;
+struct RenderEngineType;
+
+typedef struct GPULamp GPULamp;
+
+typedef struct LampEngineData {
+ struct GPUFrameBuffer *framebuffers[4];
+ struct GPUTexture *textures[4];
+ void *storage[4];
+} LampEngineData;
+
+GPULamp *GPU_lamp_from_engine(struct Scene *scene, struct Object *ob, Object *par, struct RenderEngineType *re);
+GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
+void GPU_lamp_free(struct Object *ob);
+
+bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
+void GPU_lamp_update_buffer_mats(GPULamp *lamp);
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
+int GPU_lamp_shadow_bind_code(GPULamp *lamp);
+float *GPU_lamp_dynpersmat(GPULamp *lamp);
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad);
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
+int GPU_lamp_shadow_layer(GPULamp *lamp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_LAMP_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 0d92d22a173..cbcd6383a72 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -45,7 +45,6 @@ struct Image;
struct ImageUser;
struct Material;
struct Object;
-struct Image;
struct Scene;
struct SceneRenderLayer;
struct GPUVertexAttribs;
@@ -61,7 +60,7 @@ struct World;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
typedef struct GPUMaterial GPUMaterial;
-typedef struct GPULamp GPULamp;
+
typedef struct GPUParticleInfo GPUParticleInfo;
/* Functions to create GPU Materials nodes */
@@ -224,7 +223,6 @@ void GPU_material_free(struct ListBase *gpumaterial);
void GPU_materials_free(void);
-bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock);
@@ -310,26 +308,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma);
void GPU_free_shader_export(GPUShaderExport *shader);
/* Lamps */
-
-GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
-void GPU_lamp_free(struct Object *ob);
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
-void GPU_lamp_update_buffer_mats(GPULamp *lamp);
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]);
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp);
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp);
-int GPU_lamp_shadow_bind_code(GPULamp *lamp);
-float *GPU_lamp_dynpersmat(GPULamp *lamp);
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]);
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy);
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad);
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend);
-int GPU_lamp_shadow_layer(GPULamp *lamp);
GPUNodeLink *GPU_lamp_get_data(
- GPUMaterial *mat, GPULamp *lamp,
+ GPUMaterial *mat, struct GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy);
/* World */
diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h
index 43a03f8e4b6..85b1b5c7acf 100644
--- a/source/blender/gpu/GPU_matrix.h
+++ b/source/blender/gpu/GPU_matrix.h
@@ -1,6 +1,3 @@
-#ifndef _GPU_MATRIX_H_
-#define _GPU_MATRIX_H_
-
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
@@ -32,8 +29,11 @@
* \ingroup gpu
*/
+#ifndef _GPU_MATRIX_H_
+#define _GPU_MATRIX_H_
+
+#include "BLI_sys_types.h"
#include "GPU_glew.h"
-#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@@ -84,6 +84,7 @@ void gpuTranslate3f(float x, float y, float z);
void gpuTranslate3fv(const float vec[3]);
void gpuScale3f(float x, float y, float z);
void gpuScale3fv(const float vec[3]);
+void gpuRotate3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */
void gpuRotate3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */
void gpuRotateAxis(float deg, char axis); /* TODO: enum for axis? */
@@ -105,16 +106,16 @@ void gpuRotate2D(float deg);
/* 3D Projection Matrix */
+void gpuLoadProjectionMatrix3D(const float m[4][4]);
+
void gpuOrtho(float left, float right, float bottom, float top, float near, float far);
void gpuFrustum(float left, float right, float bottom, float top, float near, float far);
void gpuPerspective(float fovy, float aspect, float near, float far);
-/* pass vector through current transform (world --> screen) */
-void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3]);
-
-/* pass vector through inverse transform (world <-- screen) */
-bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3]);
+/* 3D Projection between Window and World Space */
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]);
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]);
/* 2D Projection Matrix */
@@ -130,15 +131,6 @@ const float *gpuGetNormalMatrix(float m[3][3]);
const float *gpuGetNormalMatrixInverse(float m[3][3]);
-#if SUPPORT_LEGACY_MATRIX
-/* copy top matrix from each legacy stack into new fresh stack */
-void gpuMatrixBegin3D_legacy(void);
-
-/* call after using glScale, glTranslate, etc. between draw calls */
-void gpuMatrixUpdate_legacy(void);
-#endif
-
-
/* set uniform values for currently bound shader */
void gpuBindMatrices(GLuint program);
bool gpuMatricesDirty(void); /* since last bind */
@@ -147,4 +139,47 @@ bool gpuMatricesDirty(void); /* since last bind */
}
#endif
+
+#ifndef SUPPRESS_GENERIC_MATRIX_API
+/* make matrix inputs generic, to avoid warnings */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+# define gpuMultMatrix3D(x) \
+ gpuMultMatrix3D(_Generic((x), \
+ float *: (const float (*)[4])(x), \
+ float [16]: (const float (*)[4])(x), \
+ float (*)[4]: (const float (*)[4])(x), \
+ float [4][4]: (const float (*)[4])(x), \
+ const float *: (const float (*)[4])(x), \
+ const float [16]: (const float (*)[4])(x), \
+ const float (*)[4]: (const float (*)[4])(x), \
+ const float [4][4]: (const float (*)[4])(x)) \
+)
+# define gpuLoadMatrix3D(x) \
+ gpuLoadMatrix3D(_Generic((x), \
+ float *: (const float (*)[4])(x), \
+ float [16]: (const float (*)[4])(x), \
+ float (*)[4]: (const float (*)[4])(x), \
+ float [4][4]: (const float (*)[4])(x), \
+ const float *: (const float (*)[4])(x), \
+ const float [16]: (const float (*)[4])(x), \
+ const float (*)[4]: (const float (*)[4])(x), \
+ const float [4][4]: (const float (*)[4])(x)) \
+)
+/* TODO: finish this in a simpler way --^ */
+#else
+# define gpuMultMatrix3D(x) gpuMultMatrix3D((const float (*)[4])(x))
+# define gpuLoadMatrix3D(x) gpuLoadMatrix3D((const float (*)[4])(x))
+
+# define gpuLoadProjectionMatrix3D(x) gpuLoadProjectionMatrix3D((const float (*)[4])(x))
+
+# define gpuMultMatrix2D(x) gpuMultMatrix2D((const float (*)[3])(x))
+# define gpuLoadMatrix2D(x) gpuLoadMatrix2D((const float (*)[3])(x))
+
+# define gpuGetModelViewMatrix3D(x) gpuGetModelViewMatrix3D((float (*)[4])(x))
+# define gpuGetProjectionMatrix3D(x) gpuGetProjectionMatrix3D((float (*)[4])(x))
+# define gpuGetModelViewProjectionMatrix3D(x) gpuGetModelViewProjectionMatrix3D((float (*)[4])(x))
+# define gpuGetNormalMatrix(x) gpuGetNormalMatrix((float (*)[3])(x))
+# define gpuGetNormalMatrixInverse(x) gpuGetNormalMatrixInverse((float (*)[3])(x))
+#endif /* C11 */
+#endif /* SUPPRESS_GENERIC_MATRIX_API */
#endif /* GPU_MATRIX_H */
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 6a16b5b7456..cf5b8bf7d8f 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -30,19 +30,30 @@
#ifndef __GPU_SELECT_H__
#define __GPU_SELECT_H__
-#include "DNA_vec_types.h" /* rcft */
#include "BLI_sys_types.h"
+struct rcti;
+
/* flags for mode of operation */
enum {
GPU_SELECT_ALL = 1,
+ /* gpu_select_query */
GPU_SELECT_NEAREST_FIRST_PASS = 2,
GPU_SELECT_NEAREST_SECOND_PASS = 3,
+ /* gpu_select_pick */
+ GPU_SELECT_PICK_ALL = 4,
+ GPU_SELECT_PICK_NEAREST = 5,
};
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits);
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits);
bool GPU_select_load_id(unsigned int id);
unsigned int GPU_select_end(void);
bool GPU_select_query_check_active(void);
+/* cache selection region */
+bool GPU_select_is_cached(void);
+void GPU_select_cache_begin(void);
+void GPU_select_cache_load_id(void);
+void GPU_select_cache_end(void);
+
#endif
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index fcf070890ea..71a1e3a6591 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -71,8 +71,12 @@ void GPU_shader_bind(GPUShader *shader);
void GPU_shader_unbind(void);
int GPU_shader_get_program(GPUShader *shader);
+
void *GPU_shader_get_interface(GPUShader *shader);
-void GPU_shader_set_interface(GPUShader *shader, void *interface);
+
+void *GPU_fx_shader_get_interface(GPUShader *shader);
+void GPU_fx_shader_set_interface(GPUShader *shader, void *interface);
+
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
@@ -103,12 +107,14 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_EDGES_OVERLAY,
GPU_SHADER_KEYFRAME_DIAMOND,
GPU_SHADER_SIMPLE_LIGHTING,
+ GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR,
/* for simple 2D drawing */
GPU_SHADER_2D_UNIFORM_COLOR,
GPU_SHADER_2D_FLAT_COLOR,
GPU_SHADER_2D_SMOOTH_COLOR,
GPU_SHADER_2D_IMAGE_COLOR,
GPU_SHADER_2D_CHECKER,
+ GPU_SHADER_2D_DIAG_STRIPES,
/* for simple 3D drawing */
GPU_SHADER_3D_UNIFORM_COLOR,
GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
@@ -117,6 +123,7 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_3D_DEPTH_ONLY,
GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
/* basic image drawing */
+ GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
GPU_SHADER_3D_IMAGE_MODULATE_ALPHA,
GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA,
@@ -125,23 +132,35 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_IMAGE_INTERLACE,
/* points */
GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR,
- GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH,
- GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
- GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
+ GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA,
GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR,
GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR,
GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR,
- GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH,
- GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA,
+ GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA,
GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
+ /* lines */
+ GPU_SHADER_2D_LINE_DASHED_COLOR,
/* lamp drawing */
GPU_SHADER_3D_GROUNDPOINT,
GPU_SHADER_3D_GROUNDLINE,
GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR,
+ /* bone drawing */
+ GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR,
+ GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR,
+ /* camera drawing */
+ GPU_SHADER_CAMERA,
+ /* distance in front of objects */
+ GPU_SHADER_DISTANCE_LINES,
+ /* axis name */
+ GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS,
/* instance */
GPU_SHADER_INSTANCE_UNIFORM_COLOR,
GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE,
+ GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index a8df80cd626..93cc8443643 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -66,6 +66,7 @@ typedef enum GPUTextureFormat {
GPU_RGBA8,
GPU_RG32F,
GPU_RG16F,
+ GPU_R16F,
GPU_R8,
#if 0
GPU_RGBA32F,
@@ -87,7 +88,6 @@ typedef enum GPUTextureFormat {
GPU_R32F,
GPU_R32I,
GPU_R32UI,
- GPU_R16F,
GPU_R16I,
GPU_R16UI,
GPU_R16,
@@ -101,8 +101,8 @@ typedef enum GPUTextureFormat {
GPU_RGB10_A2,
GPU_RGB10_A2UI,
GPU_DEPTH32F_STENCIL8,
- GPU_DEPTH24_STENCIL8,
#endif
+ GPU_DEPTH24_STENCIL8,
/* Texture only format */
#if 0
@@ -155,6 +155,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char
GPUTexture *GPU_texture_create_3D_custom(
int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
+GPUTexture *GPU_texture_create_depth_with_stencil(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
GPUTexture *GPU_texture_from_blender(
@@ -183,7 +184,8 @@ void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int
int GPU_texture_target(const GPUTexture *tex);
int GPU_texture_width(const GPUTexture *tex);
int GPU_texture_height(const GPUTexture *tex);
-int GPU_texture_depth(const GPUTexture *tex);
+bool GPU_texture_depth(const GPUTexture *tex);
+bool GPU_texture_stencil(const GPUTexture *tex);
int GPU_texture_opengl_bindcode(const GPUTexture *tex);
#ifdef __cplusplus
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 9de16f64ca1..2411fe755af 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -44,7 +44,7 @@ typedef struct GPUViewport GPUViewport;
#define MAX_BUFFERS 8
#define MAX_TEXTURES 16
#define MAX_PASSES 16
-#define MAX_STORAGE 2 /* extend if needed */
+#define MAX_STORAGE 5 /* extend if needed */
/* All FramebufferLists are just the same pointers with different names */
typedef struct FramebufferList {
@@ -56,34 +56,40 @@ typedef struct TextureList {
} TextureList;
typedef struct PassList {
- struct DRWPass *passes[MAX_TEXTURES];
+ struct DRWPass *passes[MAX_PASSES];
} PassList;
typedef struct StorageList {
void *storage[MAX_STORAGE]; /* custom structs from the engine */
} StorageList;
-/* Buffer and textures used by the viewport by default */
-typedef struct DefaultFramebufferList {
- struct GPUFrameBuffer *default_fb;
-} DefaultFramebufferList;
+typedef struct ViewportEngineData {
+ void *engine_type;
-typedef struct DefaultTextureList {
- struct GPUTexture *color;
- struct GPUTexture *depth;
-} DefaultTextureList;
+ FramebufferList *fbl;
+ TextureList *txl;
+ PassList *psl;
+ StorageList *stl;
-typedef struct DefaultPassList {
- struct DRWPass *non_meshes_pass;
- struct DRWPass *ob_center_pass;
-} DefaultPassList;
+ /* Profiling data */
+ double init_time;
+ double cache_time;
+ double render_time;
+ double background_time;
+} ViewportEngineData;
GPUViewport *GPU_viewport_create(void);
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine);
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
void GPU_viewport_unbind(GPUViewport *viewport);
void GPU_viewport_free(GPUViewport *viewport);
-void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str);
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport);
+void *GPU_viewport_texture_list_get(GPUViewport *viewport);
+void GPU_viewport_size_get(GPUViewport *viewport, int *size);
+
+bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash);
/* debug */
bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c
index 757982d1b30..960181df545 100644
--- a/source/blender/gpu/intern/gpu_basic_shader.c
+++ b/source/blender/gpu/intern/gpu_basic_shader.c
@@ -159,24 +159,6 @@ const GLubyte stipple_hexagon[128] = {
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
/* ********************************************* */
-/* GLSL State */
-
-static bool USE_GLSL = true;
-
-/**
- * \note this isn't part of the basic shader API,
- * only set from the command line once on startup.
- */
-void GPU_basic_shader_use_glsl_set(bool enabled)
-{
- USE_GLSL = enabled;
-}
-
-bool GPU_basic_shader_use_glsl_get(void)
-{
- return USE_GLSL;
-}
-
/* Init / exit */
void GPU_basic_shaders_init(void)
@@ -312,85 +294,16 @@ static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options)
void GPU_basic_shader_bind(int options)
{
- if (USE_GLSL) {
- if (options) {
- GPUShader *shader = gpu_basic_shader(options);
+ if (options) {
+ GPUShader *shader = gpu_basic_shader(options);
- if (shader) {
- GPU_shader_bind(shader);
- GPU_basic_shader_uniform_autoset(shader, options);
- }
- }
- else {
- GPU_shader_unbind();
+ if (shader) {
+ GPU_shader_bind(shader);
+ GPU_basic_shader_uniform_autoset(shader, options);
}
}
else {
- const int bound_options = GPU_MATERIAL_STATE.bound_options;
-
- if (options & GPU_SHADER_LIGHTING) {
- glEnable(GL_LIGHTING);
-
- if (options & GPU_SHADER_USE_COLOR)
- glEnable(GL_COLOR_MATERIAL);
- else
- glDisable(GL_COLOR_MATERIAL);
-
- if (options & GPU_SHADER_TWO_SIDED)
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
- else
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
- else if (bound_options & GPU_SHADER_LIGHTING) {
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
- glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
- }
-
- if (options & GPU_SHADER_TEXTURE_2D) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_2D) {
- if ((options & GPU_SHADER_TEXTURE_RECT) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_2D);
- }
-
- if (options & GPU_SHADER_TEXTURE_RECT) {
- GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE;
- glEnable(GL_TEXTURE_RECTANGLE);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode);
- }
- else if (bound_options & GPU_SHADER_TEXTURE_RECT) {
- if ((options & GPU_SHADER_TEXTURE_2D) == 0) {
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- }
- glDisable(GL_TEXTURE_RECTANGLE);
- }
-
- if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_LINE_STIPPLE);
- }
- else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_LINE_STIPPLE);
- }
-
- if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) {
- glEnable(GL_POLYGON_STIPPLE);
- }
- else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) {
- glDisable(GL_POLYGON_STIPPLE);
- }
-
- if (options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_FLAT);
- }
- else if (bound_options & GPU_SHADER_FLAT_NORMAL) {
- glShadeModel(GL_SMOOTH);
- }
+ GPU_shader_unbind();
}
GPU_MATERIAL_STATE.bound_options = options;
@@ -500,14 +413,12 @@ void GPU_basic_shader_light_set(int light_num, GPULightData *light)
}
else {
/* TODO(sergey): Needs revisit. */
- if (USE_GLSL || true) {
- /* glsl shader needs these zero to skip them */
- const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* glsl shader needs these zero to skip them */
+ const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
- glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
- }
+ glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero);
+ glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero);
+ glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero);
glDisable(GL_LIGHT0 + light_num);
}
@@ -520,56 +431,19 @@ void GPU_basic_shader_light_set_viewer(bool local)
void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
- }
- else {
- switch (stipple_id) {
- case GPU_SHADER_STIPPLE_HALFTONE:
- glPolygonStipple(stipple_halftone);
- return;
- case GPU_SHADER_STIPPLE_QUARTTONE:
- glPolygonStipple(stipple_quarttone);
- return;
- case GPU_SHADER_STIPPLE_CHECKER_8PX:
- glPolygonStipple(stipple_checker_8px);
- return;
- case GPU_SHADER_STIPPLE_HEXAGON:
- glPolygonStipple(stipple_hexagon);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP:
- glPolygonStipple(stipple_diag_stripes_neg);
- return;
- case GPU_SHADER_STIPPLE_DIAG_STRIPES:
- glPolygonStipple(stipple_diag_stripes_pos);
- return;
- default:
- glPolygonStipple(stipple_hexagon);
- return;
- }
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id);
}
void GPU_basic_shader_line_width(float line_width)
{
- if (USE_GLSL) {
- GPU_MATERIAL_STATE.line_width = line_width;
- if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
- glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
- }
- }
- else {
- glLineWidth(line_width);
+ GPU_MATERIAL_STATE.line_width = line_width;
+ if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) {
+ glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width);
}
}
void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern)
{
- if (USE_GLSL) {
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
- glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
- }
- else {
- glLineStipple(stipple_factor, stipple_pattern);
- }
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor);
+ glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern);
}
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 716c5e55b3c..65a827febde 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -31,7 +31,7 @@
#include "GPU_batch.h"
#include "gpu_shader_private.h"
-void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id)
+void Batch_set_builtin_program(Batch *batch, GPUBuiltinShader shader_id)
{
GPUShader *shader = GPU_shader_get_builtin_shader(shader_id);
Batch_set_program(batch, shader->program);
@@ -40,6 +40,8 @@ void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id)
static Batch *sphere_high = NULL;
static Batch *sphere_med = NULL;
static Batch *sphere_low = NULL;
+static Batch *sphere_wire_low = NULL;
+static Batch *sphere_wire_med = NULL;
static VertexBuffer *vbo;
static VertexFormat format = {0};
@@ -70,23 +72,23 @@ static Batch *batch_sphere(int lat_res, int lon_res)
}
vbo = VertexBuffer_create_with_format(&format);
- VertexBuffer_allocate_data(vbo, (lat_res-1) * lon_res * 6);
+ VertexBuffer_allocate_data(vbo, (lat_res - 1) * lon_res * 6);
vert = 0;
lon = 0.0f;
- for(int i = 0; i < lon_res; i++, lon += lon_inc) {
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
lat = 0.0f;
- for(int j = 0; j < lat_res; j++, lat += lat_inc) {
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
if (j != lat_res - 1) { /* Pole */
- batch_sphere_lat_lon_vert(lat, lon);
- batch_sphere_lat_lon_vert(lat+lat_inc, lon);
- batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(lat, lon);
}
if (j != 0) { /* Pole */
- batch_sphere_lat_lon_vert(lat, lon);
- batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc);
- batch_sphere_lat_lon_vert(lat, lon+lon_inc);
+ batch_sphere_lat_lon_vert(lat, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat, lon);
}
}
}
@@ -94,6 +96,38 @@ static Batch *batch_sphere(int lat_res, int lon_res)
return Batch_create(GL_TRIANGLES, vbo, NULL);
}
+static Batch *batch_sphere_wire(int lat_res, int lon_res)
+{
+ const float lon_inc = 2 * M_PI / lon_res;
+ const float lat_inc = M_PI / lat_res;
+ float lon, lat;
+
+ if (format.attrib_ct == 0) {
+ pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+ nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT);
+ }
+
+ vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2));
+ vert = 0;
+
+ lon = 0.0f;
+ for (int i = 0; i < lon_res; i++, lon += lon_inc) {
+ lat = 0.0f;
+ for (int j = 0; j < lat_res; j++, lat += lat_inc) {
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ batch_sphere_lat_lon_vert(lat, lon);
+
+ if (j != lat_res - 1) { /* Pole */
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc);
+ batch_sphere_lat_lon_vert(lat + lat_inc, lon);
+ }
+ }
+ }
+
+ return Batch_create(GL_LINES, vbo, NULL);
+}
+
Batch *Batch_get_sphere(int lod)
{
BLI_assert(lod >= 0 && lod <= 2);
@@ -106,12 +140,25 @@ Batch *Batch_get_sphere(int lod)
return sphere_high;
}
+Batch *Batch_get_sphere_wire(int lod)
+{
+ BLI_assert(lod >= 0 && lod <= 1);
+
+ if (lod == 0)
+ return sphere_wire_low;
+ else
+ return sphere_wire_med;
+}
+
void gpu_batch_init(void)
{
/* Hard coded resolution */
- sphere_low = batch_sphere(8, 8);
+ sphere_low = batch_sphere(8, 16);
sphere_med = batch_sphere(16, 10);
sphere_high = batch_sphere(32, 24);
+
+ sphere_wire_low = batch_sphere_wire(6, 8);
+ sphere_wire_med = batch_sphere_wire(8, 16);
}
void gpu_batch_exit(void)
@@ -119,4 +166,6 @@ void gpu_batch_exit(void)
Batch_discard_all(sphere_low);
Batch_discard_all(sphere_med);
Batch_discard_all(sphere_high);
+ Batch_discard_all(sphere_wire_low);
+ Batch_discard_all(sphere_wire_med);
}
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 370841327aa..6492cf90929 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -56,6 +56,7 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "bmesh.h"
@@ -2033,59 +2034,57 @@ void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer)
}
/* debug function, draws the pbvh BB */
-void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
+void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos)
{
- const float quads[4][4][3] = {
- {
- {min[0], min[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {min[0], min[1], max[2]}
- },
-
- {
- {min[0], min[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {min[0], min[1], max[2]}
- },
-
- {
- {max[0], max[1], min[2]},
- {max[0], min[1], min[2]},
- {max[0], min[1], max[2]},
- {max[0], max[1], max[2]}
- },
-
- {
- {max[0], max[1], min[2]},
- {min[0], max[1], min[2]},
- {min[0], max[1], max[2]},
- {max[0], max[1], max[2]}
- },
- };
-
if (leaf)
- glColor4f(0.0, 1.0, 0.0, 0.5);
+ immUniformColor4f(0.0, 1.0, 0.0, 0.5);
else
- glColor4f(1.0, 0.0, 0.0, 0.5);
+ immUniformColor4f(1.0, 0.0, 0.0, 0.5);
- glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]);
- glDrawArrays(GL_QUADS, 0, 16);
-}
+ /* TODO(merwin): revisit this after we have mutable VertexBuffers
+ * could keep a static batch & index buffer, change the VBO contents per draw
+ */
-void GPU_init_draw_pbvh_BB(void)
-{
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_CULL_FACE);
- glEnableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
- glEnable(GL_BLEND);
-}
+ immBegin(PRIM_LINES, 24);
-void GPU_end_draw_pbvh_BB(void)
-{
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glPopAttrib();
+ /* top */
+ immVertex3f(pos, min[0], min[1], max[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
+
+ immVertex3f(pos, min[0], max[1], max[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], max[1], max[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
+
+ immVertex3f(pos, max[0], min[1], max[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
+
+ /* bottom */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], max[1], min[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], min[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], min[1], min[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], min[2]);
+
+ /* sides */
+ immVertex3f(pos, min[0], min[1], min[2]);
+ immVertex3f(pos, min[0], min[1], max[2]);
+
+ immVertex3f(pos, min[0], max[1], min[2]);
+ immVertex3f(pos, min[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], max[1], min[2]);
+ immVertex3f(pos, max[0], max[1], max[2]);
+
+ immVertex3f(pos, max[0], min[1], min[2]);
+ immVertex3f(pos, max[0], min[1], max[2]);
+
+ immEnd();
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 4223ec54f74..df3b6f962e5 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -360,7 +360,7 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
for (i = 0; i < type; i++) {
- BLI_dynstr_appendf(ds, "%f", data[i]);
+ BLI_dynstr_appendf(ds, "%.12f", data[i]);
if (i == type - 1)
BLI_dynstr_append(ds, ")");
else
@@ -653,7 +653,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ");\n");
}
- BLI_dynstr_append(ds, "\n\tgl_FragColor = ");
+ BLI_dynstr_append(ds, "\n\tfragColor = ");
codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id);
BLI_dynstr_append(ds, ";\n");
}
@@ -788,7 +788,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
#endif
BLI_dynstr_appendf(
- ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n",
+ ds, "\tvar%d.xyz = normalize(NormalMatrix * att%d.xyz);\n",
input->attribid, input->attribid);
BLI_dynstr_appendf(
ds, "\tvar%d.w = att%d.w;\n",
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 528bdefc209..5214b6b1ab7 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -47,6 +47,7 @@
#include "GPU_glew.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
+#include "GPU_batch.h"
#include "MEM_guardedalloc.h"
@@ -193,7 +194,8 @@ struct GPUFX {
/* we have a stencil, restore the previous state */
bool restore_stencil;
- unsigned int vbuffer;
+ Batch *quad_batch;
+ Batch *point_batch;
};
#if 0
@@ -269,12 +271,32 @@ GPUFX *GPU_fx_compositor_create(void)
{
GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
- glGenBuffers(1, &fx->vbuffer);
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STATIC_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(float), fullscreencos);
- glBufferSubData(GL_ARRAY_BUFFER, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
+ /* Quad buffer */
+ static VertexFormat format = {0};
+ static unsigned int pos, uvs;
+ if (format.attrib_ct == 0) {
+ pos = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ uvs = add_attrib(&format, "uvs", GL_FLOAT, 2, KEEP_FLOAT);
+ }
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, 4);
+ for (int i = 0; i < 4; ++i) {
+ setAttrib(vbo, pos, i, fullscreencos[i]);
+ setAttrib(vbo, uvs, i, fullscreenuvs[i]);
+ }
+ fx->quad_batch = Batch_create(GL_TRIANGLE_STRIP, vbo, NULL);
+
+ /* Point Buffer */
+ static VertexFormat format_point = {0};
+ static unsigned int dummy_attrib;
+ if (format_point.attrib_ct == 0) {
+ dummy_attrib = add_attrib(&format_point, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ }
+ float dummy[2] = {0.0f, 0.0f};
+ VertexBuffer *vbo_point = VertexBuffer_create_with_format(&format_point);
+ VertexBuffer_allocate_data(vbo_point, 1);
+ setAttrib(vbo_point, dummy_attrib, 0, &dummy);
+ fx->point_batch = Batch_create(GL_POINTS, vbo_point, NULL);
return fx;
}
@@ -364,7 +386,8 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
void GPU_fx_compositor_destroy(GPUFX *fx)
{
cleanup_fx_gl_data(fx, true);
- glDeleteBuffers(1, &fx->vbuffer);
+ Batch_discard_all(fx->quad_batch);
+ Batch_discard_all(fx->point_batch);
MEM_freeN(fx);
}
@@ -702,19 +725,13 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
/* disable writing to color buffer, it's depth only pass */
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false);
if (depth_resolve_shader) {
- GPUDepthResolveInterface *interface = GPU_shader_get_interface(depth_resolve_shader);
+ GPUDepthResolveInterface *interface = GPU_fx_shader_get_interface(depth_resolve_shader);
- GPU_shader_bind(depth_resolve_shader);
+ /* set up quad buffer */
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(depth_resolve_shader));
GPU_texture_bind(fx->depth_buffer_xray, 0);
GPU_texture_compare_mode(fx->depth_buffer_xray, false);
@@ -722,7 +739,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
/* draw */
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_compare_mode(fx->depth_buffer_xray, true);
@@ -734,10 +751,6 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
glPopAttrib();
}
@@ -774,13 +787,6 @@ bool GPU_fx_do_composite_pass(
src = fx->color_buffer;
target = fx->color_buffer_sec;
- /* set up quad buffer */
- glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer);
- glVertexPointer(2, GL_FLOAT, 0, NULL);
- glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float)));
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
/* full screen FX pass */
/* invert the view matrix */
@@ -808,8 +814,6 @@ bool GPU_fx_do_composite_pass(
viewvecs[1][2] = vec_far[2] - viewvecs[0][2];
}
- /* set invalid color in case shader fails */
- glColor3f(1.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);
/* ssao pass */
@@ -828,9 +832,9 @@ bool GPU_fx_do_composite_pass(
ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
- GPUSSAOShaderInterface *interface = GPU_shader_get_interface(ssao_shader);
+ GPUSSAOShaderInterface *interface = GPU_fx_shader_get_interface(ssao_shader);
- GPU_shader_bind(ssao_shader);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(ssao_shader));
GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params);
GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color);
@@ -854,7 +858,7 @@ bool GPU_fx_do_composite_pass(
/* draw */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(src);
@@ -912,11 +916,8 @@ bool GPU_fx_do_composite_pass(
if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) {
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return false;
}
@@ -924,9 +925,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
- GPUDOFHQPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
+ GPUDOFHQPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
- GPU_shader_bind(dof_shader_pass1);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1));
GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -953,7 +954,8 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_check_valid(fx->gbuffer, NULL);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
+
/* disable bindings */
GPU_texture_filter_mode(src, true);
GPU_texture_unbind(src);
@@ -975,19 +977,18 @@ bool GPU_fx_do_composite_pass(
int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
float selection[2] = {0.0f, 1.0f};
- GPUDOFHQPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
+ GPUDOFHQPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
- GPU_shader_bind(dof_shader_pass2);
+ Batch_set_program(fx->point_batch, GPU_shader_get_program(dof_shader_pass2));
+
+ GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
+ GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
+ GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim);
GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
-
- GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc);
-
- GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
- GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
GPU_texture_filter_mode(fx->dof_half_downsampled_far, false);
@@ -1003,24 +1004,24 @@ bool GPU_fx_do_composite_pass(
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+ Batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL);
GPU_texture_unbind(fx->dof_half_downsampled_far);
GPU_framebuffer_texture_detach(fx->dof_far_blur);
- GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
-
selection[0] = 1.0f;
selection[1] = 0.0f;
GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection);
+ GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0);
/* have to clear the buffer unfortunately */
glClear(GL_COLOR_BUFFER_BIT);
/* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */
- glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h);
+ Batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL);
+ Batch_done_using_program(fx->point_batch);
/* disable bindings */
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -1032,15 +1033,16 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_nearfar_coc);
GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
+ numslots = 0;
}
/* third pass, accumulate the near/far blur fields */
{
float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
- GPUDOFHQPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
+ GPUDOFHQPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
- GPU_shader_bind(dof_shader_pass3);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3));
GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params);
@@ -1066,7 +1068,7 @@ bool GPU_fx_do_composite_pass(
/* if this is the last pass, prepare for rendering on the frambuffer */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_blur);
@@ -1108,11 +1110,8 @@ bool GPU_fx_do_composite_pass(
if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) {
GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
GPU_framebuffer_restore();
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
GPU_shader_unbind();
- glBindBuffer(GL_ARRAY_BUFFER, 0);
return false;
}
@@ -1120,9 +1119,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
- GPUDOFPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1);
+ GPUDOFPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1);
- GPU_shader_bind(dof_shader_pass1);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1));
GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -1141,7 +1140,7 @@ bool GPU_fx_do_composite_pass(
/* binding takes care of setting the viewport to the downsampled size */
GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(src);
GPU_texture_compare_mode(fx->depth_buffer, true);
@@ -1159,12 +1158,12 @@ bool GPU_fx_do_composite_pass(
float tmp = invrendertargetdim[0];
invrendertargetdim[0] = 0.0f;
- GPUDOFPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2);
+ GPUDOFPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2);
dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
/* Blurring vertically */
- GPU_shader_bind(dof_shader_pass2);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2));
GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -1182,10 +1181,14 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0);
/* Drawing quad */
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
+
+ /* Rebind Shader */
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2));
/* *unbind/detach */
GPU_texture_unbind(fx->dof_near_coc_buffer);
+
GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
/* Blurring horizontally */
@@ -1197,7 +1200,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer);
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ Batch_draw(fx->quad_batch);
/* *unbind/detach */
GPU_texture_compare_mode(fx->depth_buffer, true);
@@ -1214,9 +1218,9 @@ bool GPU_fx_do_composite_pass(
/* third pass, calculate near coc */
{
- GPUDOFPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3);
+ GPUDOFPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3);
- GPU_shader_bind(dof_shader_pass3);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3));
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer);
@@ -1226,7 +1230,7 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_coc_buffer);
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
@@ -1242,9 +1246,9 @@ bool GPU_fx_do_composite_pass(
float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer),
1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)};
- GPUDOFPassFourInterface *interface = GPU_shader_get_interface(dof_shader_pass4);
+ GPUDOFPassFourInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass4);
- GPU_shader_bind(dof_shader_pass4);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass4));
GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer);
@@ -1252,7 +1256,7 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
@@ -1267,9 +1271,9 @@ bool GPU_fx_do_composite_pass(
{
float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
- GPUDOFPassFiveInterface *interface = GPU_shader_get_interface(dof_shader_pass5);
+ GPUDOFPassFiveInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass5);
- GPU_shader_bind(dof_shader_pass5);
+ Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass5));
GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params);
GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
@@ -1292,7 +1296,7 @@ bool GPU_fx_do_composite_pass(
/* if this is the last pass, prepare for rendering on the frambuffer */
gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ Batch_draw(fx->quad_batch);
/* disable bindings */
GPU_texture_unbind(fx->dof_near_coc_buffer);
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
@@ -1318,10 +1322,6 @@ bool GPU_fx_do_composite_pass(
}
}
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
GPU_shader_unbind();
return true;
@@ -1363,7 +1363,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex");
interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1377,7 +1377,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1391,7 +1391,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection");
interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1407,7 +1407,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1421,7 +1421,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
@@ -1434,7 +1434,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
@@ -1444,7 +1444,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
@@ -1454,7 +1454,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer");
interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
@@ -1469,7 +1469,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
@@ -1479,7 +1479,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef
interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer");
- GPU_shader_set_interface(shader, interface);
+ GPU_fx_shader_set_interface(shader, interface);
break;
}
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
index e306394c4c3..eeeb6e0ab33 100644
--- a/source/blender/gpu/intern/gpu_debug.c
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -20,7 +20,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): Brecht Van Lommel, Jason Wilkins.
+ * Contributor(s): Brecht Van Lommel, Jason Wilkins, Mike Erwin.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -43,19 +43,21 @@
#include <stdlib.h>
#include <string.h>
-/* control whether we use older AMD_debug_output extension, or just the newer extensions
- * TODO(merwin): determine whether all supported GPU + OS combos have newer extensions */
-#define LEGACY_DEBUG 0
+#ifndef __APPLE__ /* only non-Apple systems implement OpenGL debug callbacks */
+
+/* control whether we use older AMD_debug_output extension
+ * some supported GPU + OS combos do not have the newer extensions */
+# define LEGACY_DEBUG 1
/* Debug callbacks need the same calling convention as OpenGL functions. */
-#if defined(_WIN32)
-# define APIENTRY __stdcall
-#else
-# define APIENTRY
-#endif
+# if defined(_WIN32)
+# define APIENTRY __stdcall
+# else
+# define APIENTRY
+# endif
-static const char* source_name(GLenum source)
+static const char *source_name(GLenum source)
{
switch (source) {
case GL_DEBUG_SOURCE_API: return "API";
@@ -68,7 +70,7 @@ static const char* source_name(GLenum source)
}
}
-static const char* message_type_name(GLenum message)
+static const char *message_type_name(GLenum message)
{
switch (message) {
case GL_DEBUG_TYPE_ERROR: return "error";
@@ -105,9 +107,9 @@ static void APIENTRY gpu_debug_proc(
}
}
-#if LEGACY_DEBUG
+# if LEGACY_DEBUG
-static const char* category_name_amd(GLenum category)
+static const char *category_name_amd(GLenum category)
{
switch (category) {
case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error";
@@ -143,12 +145,16 @@ static void APIENTRY gpu_debug_proc_amd(
fflush(stderr);
}
}
-#endif /* LEGACY_DEBUG */
+# endif /* LEGACY_DEBUG */
-#undef APIENTRY
+# undef APIENTRY
+#endif /* not Apple */
void gpu_debug_init(void)
{
+#ifdef __APPLE__
+ fprintf(stderr, "OpenGL debug callback is not available on Apple.\n");
+#else /* not Apple */
const char success[] = "Successfully hooked OpenGL debug callback.";
if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
@@ -166,37 +172,43 @@ void gpu_debug_init(void)
glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
}
-#if LEGACY_DEBUG
+# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
fprintf(stderr, "Using AMD_debug_output extension\n");
glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
GPU_string_marker(success);
}
-#endif
+# endif
else {
fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
}
+#endif /* not Apple */
}
void gpu_debug_exit(void)
{
+#ifndef __APPLE__
if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageCallback(NULL, NULL);
}
else if (GLEW_ARB_debug_output) {
glDebugMessageCallbackARB(NULL, NULL);
}
-#if LEGACY_DEBUG
+# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
glDebugMessageCallbackAMD(NULL, NULL);
}
+# endif
#endif
}
void GPU_string_marker(const char *buf)
{
+#ifdef __APPLE__
+ UNUSED_VARS(buf);
+#else /* not Apple */
if (GLEW_VERSION_4_3 || GLEW_KHR_debug) {
glDebugMessageInsert(
GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
@@ -207,13 +219,14 @@ void GPU_string_marker(const char *buf)
GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0,
GL_DEBUG_SEVERITY_LOW_ARB, -1, buf);
}
-#if LEGACY_DEBUG
+# if LEGACY_DEBUG
else if (GLEW_AMD_debug_output) {
glDebugMessageInsertAMD(
GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0,
0, buf);
}
-#endif
+# endif
+#endif /* not Apple */
}
void GPU_print_error_debug(const char *str)
@@ -221,390 +234,3 @@ void GPU_print_error_debug(const char *str)
if (G.debug & G_DEBUG)
fprintf(stderr, "GPU: %s\n", str);
}
-
-static void gpu_state_print_fl_ex(const char *name, GLenum type)
-{
- const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
-
- float value[32];
- int a;
-
- memset(value, 0xff, sizeof(value));
- glGetFloatv(type, value);
-
- if (glGetError() == GL_NO_ERROR) {
- printf("%s: ", name);
- for (a = 0; a < 32; a++) {
- if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
- break;
- }
- printf("%.2f ", value[a]);
- }
- printf("\n");
- }
-}
-
-#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
-
-void GPU_state_print(void)
-{
- /* clear any errors */
- while (glGetError() != GL_NO_ERROR) {}
-
- gpu_state_print_fl(GL_ACCUM_ALPHA_BITS);
- gpu_state_print_fl(GL_ACCUM_BLUE_BITS);
- gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE);
- gpu_state_print_fl(GL_ACCUM_GREEN_BITS);
- gpu_state_print_fl(GL_ACCUM_RED_BITS);
- gpu_state_print_fl(GL_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_ALPHA_BIAS);
- gpu_state_print_fl(GL_ALPHA_BITS);
- gpu_state_print_fl(GL_ALPHA_SCALE);
- gpu_state_print_fl(GL_ALPHA_TEST);
- gpu_state_print_fl(GL_ALPHA_TEST_FUNC);
- gpu_state_print_fl(GL_ALPHA_TEST_REF);
- gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_AUTO_NORMAL);
- gpu_state_print_fl(GL_AUX_BUFFERS);
- gpu_state_print_fl(GL_BLEND);
- gpu_state_print_fl(GL_BLEND_COLOR);
- gpu_state_print_fl(GL_BLEND_DST_ALPHA);
- gpu_state_print_fl(GL_BLEND_DST_RGB);
- gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA);
- gpu_state_print_fl(GL_BLEND_EQUATION_RGB);
- gpu_state_print_fl(GL_BLEND_SRC_ALPHA);
- gpu_state_print_fl(GL_BLEND_SRC_RGB);
- gpu_state_print_fl(GL_BLUE_BIAS);
- gpu_state_print_fl(GL_BLUE_BITS);
- gpu_state_print_fl(GL_BLUE_SCALE);
- gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE);
- gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_CLIP_PLANE0);
- gpu_state_print_fl(GL_COLOR_ARRAY);
- gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_COLOR_CLEAR_VALUE);
- gpu_state_print_fl(GL_COLOR_LOGIC_OP);
- gpu_state_print_fl(GL_COLOR_MATERIAL);
- gpu_state_print_fl(GL_COLOR_MATERIAL_FACE);
- gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER);
- gpu_state_print_fl(GL_COLOR_MATRIX);
- gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_COLOR_SUM);
- gpu_state_print_fl(GL_COLOR_TABLE);
- gpu_state_print_fl(GL_COLOR_WRITEMASK);
- gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_CONVOLUTION_1D);
- gpu_state_print_fl(GL_CONVOLUTION_2D);
- gpu_state_print_fl(GL_CULL_FACE);
- gpu_state_print_fl(GL_CULL_FACE_MODE);
- gpu_state_print_fl(GL_CURRENT_COLOR);
- gpu_state_print_fl(GL_CURRENT_FOG_COORD);
- gpu_state_print_fl(GL_CURRENT_INDEX);
- gpu_state_print_fl(GL_CURRENT_NORMAL);
- gpu_state_print_fl(GL_CURRENT_PROGRAM);
- gpu_state_print_fl(GL_CURRENT_RASTER_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE);
- gpu_state_print_fl(GL_CURRENT_RASTER_INDEX);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION);
- gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID);
- gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS);
- gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR);
- gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS);
- gpu_state_print_fl(GL_DEPTH_BIAS);
- gpu_state_print_fl(GL_DEPTH_BITS);
- gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE);
- gpu_state_print_fl(GL_DEPTH_FUNC);
- gpu_state_print_fl(GL_DEPTH_RANGE);
- gpu_state_print_fl(GL_DEPTH_SCALE);
- gpu_state_print_fl(GL_DEPTH_TEST);
- gpu_state_print_fl(GL_DEPTH_WRITEMASK);
- gpu_state_print_fl(GL_DITHER);
- gpu_state_print_fl(GL_DOUBLEBUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER);
- gpu_state_print_fl(GL_DRAW_BUFFER0);
- gpu_state_print_fl(GL_EDGE_FLAG);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE);
- gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE);
- gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE);
- gpu_state_print_fl(GL_FOG);
- gpu_state_print_fl(GL_FOG_COLOR);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_FOG_COORD_SRC);
- gpu_state_print_fl(GL_FOG_DENSITY);
- gpu_state_print_fl(GL_FOG_END);
- gpu_state_print_fl(GL_FOG_HINT);
- gpu_state_print_fl(GL_FOG_INDEX);
- gpu_state_print_fl(GL_FOG_MODE);
- gpu_state_print_fl(GL_FOG_START);
- gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB); /* TODO: remove ARB program support */
- gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT);
- gpu_state_print_fl(GL_FRONT_FACE);
- gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT);
- gpu_state_print_fl(GL_GREEN_BIAS);
- gpu_state_print_fl(GL_GREEN_BITS);
- gpu_state_print_fl(GL_GREEN_SCALE);
- gpu_state_print_fl(GL_HISTOGRAM);
- gpu_state_print_fl(GL_INDEX_ARRAY);
- gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_INDEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_INDEX_BITS);
- gpu_state_print_fl(GL_INDEX_CLEAR_VALUE);
- gpu_state_print_fl(GL_INDEX_LOGIC_OP);
- gpu_state_print_fl(GL_INDEX_MODE);
- gpu_state_print_fl(GL_INDEX_OFFSET);
- gpu_state_print_fl(GL_INDEX_SHIFT);
- gpu_state_print_fl(GL_INDEX_WRITEMASK);
- gpu_state_print_fl(GL_LIGHT0);
- gpu_state_print_fl(GL_LIGHT1);
- gpu_state_print_fl(GL_LIGHT2);
- gpu_state_print_fl(GL_LIGHT3);
- gpu_state_print_fl(GL_LIGHT4);
- gpu_state_print_fl(GL_LIGHT5);
- gpu_state_print_fl(GL_LIGHT6);
- gpu_state_print_fl(GL_LIGHT7);
- gpu_state_print_fl(GL_LIGHTING);
- gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT);
- gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL);
- gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER);
- gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE);
- gpu_state_print_fl(GL_LINE_SMOOTH);
- gpu_state_print_fl(GL_LINE_SMOOTH_HINT);
- gpu_state_print_fl(GL_LINE_STIPPLE);
- gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN);
- gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT);
- gpu_state_print_fl(GL_LINE_WIDTH);
- gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_LIST_BASE);
- gpu_state_print_fl(GL_LIST_INDEX);
- gpu_state_print_fl(GL_LIST_MODE);
- gpu_state_print_fl(GL_LOGIC_OP);
- gpu_state_print_fl(GL_LOGIC_OP_MODE);
- gpu_state_print_fl(GL_MAP1_COLOR_4);
- gpu_state_print_fl(GL_MAP1_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP1_INDEX);
- gpu_state_print_fl(GL_MAP1_NORMAL);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP1_VERTEX_3);
- gpu_state_print_fl(GL_MAP1_VERTEX_4);
- gpu_state_print_fl(GL_MAP2_COLOR_4);
- gpu_state_print_fl(GL_MAP2_GRID_DOMAIN);
- gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS);
- gpu_state_print_fl(GL_MAP2_INDEX);
- gpu_state_print_fl(GL_MAP2_NORMAL);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3);
- gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4);
- gpu_state_print_fl(GL_MAP2_VERTEX_3);
- gpu_state_print_fl(GL_MAP2_VERTEX_4);
- gpu_state_print_fl(GL_MAP_COLOR);
- gpu_state_print_fl(GL_MAP_STENCIL);
- gpu_state_print_fl(GL_MATRIX_MODE);
- gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_CLIP_PLANES);
- gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_DRAW_BUFFERS);
- gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES);
- gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES);
- gpu_state_print_fl(GL_MAX_EVAL_ORDER);
- gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_LIGHTS);
- gpu_state_print_fl(GL_MAX_LIST_NESTING);
- gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE);
- gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_COORDS);
- gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS);
- gpu_state_print_fl(GL_MAX_TEXTURE_SIZE);
- gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_MAX_TEXTURE_UNITS);
- gpu_state_print_fl(GL_MAX_VARYING_FLOATS);
- gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS);
- gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
- gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS);
- gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS);
- gpu_state_print_fl(GL_MINMAX);
- gpu_state_print_fl(GL_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH);
- gpu_state_print_fl(GL_MULTISAMPLE);
- gpu_state_print_fl(GL_NAME_STACK_DEPTH);
- gpu_state_print_fl(GL_NORMALIZE);
- gpu_state_print_fl(GL_NORMAL_ARRAY);
- gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE);
- gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE);
- gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS);
- gpu_state_print_fl(GL_PACK_ALIGNMENT);
- gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_PACK_LSB_FIRST);
- gpu_state_print_fl(GL_PACK_ROW_LENGTH);
- gpu_state_print_fl(GL_PACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_PACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_PACK_SKIP_ROWS);
- gpu_state_print_fl(GL_PACK_SWAP_BYTES);
- gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT);
- gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE);
- gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE);
- gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING);
- gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION);
- gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE);
- gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_POINT_SIZE_MAX);
- gpu_state_print_fl(GL_POINT_SIZE_MIN);
- gpu_state_print_fl(GL_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_POINT_SMOOTH);
- gpu_state_print_fl(GL_POINT_SMOOTH_HINT);
- gpu_state_print_fl(GL_POINT_SPRITE);
- gpu_state_print_fl(GL_POLYGON_MODE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR);
- gpu_state_print_fl(GL_POLYGON_OFFSET_FILL);
- gpu_state_print_fl(GL_POLYGON_OFFSET_LINE);
- gpu_state_print_fl(GL_POLYGON_OFFSET_POINT);
- gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS);
- gpu_state_print_fl(GL_POLYGON_SMOOTH);
- gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT);
- gpu_state_print_fl(GL_POLYGON_STIPPLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS);
- gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS);
- gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE);
- gpu_state_print_fl(GL_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH);
- gpu_state_print_fl(GL_READ_BUFFER);
- gpu_state_print_fl(GL_RED_BIAS);
- gpu_state_print_fl(GL_RED_BITS);
- gpu_state_print_fl(GL_RED_SCALE);
- gpu_state_print_fl(GL_RENDER_MODE);
- gpu_state_print_fl(GL_RESCALE_NORMAL);
- gpu_state_print_fl(GL_RGBA_MODE);
- gpu_state_print_fl(GL_SAMPLES);
- gpu_state_print_fl(GL_SAMPLE_BUFFERS);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT);
- gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE);
- gpu_state_print_fl(GL_SCISSOR_BOX);
- gpu_state_print_fl(GL_SCISSOR_TEST);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE);
- gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE);
- gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE);
- gpu_state_print_fl(GL_SEPARABLE_2D);
- gpu_state_print_fl(GL_SHADE_MODEL);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY);
- gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE);
- gpu_state_print_fl(GL_STENCIL_BACK_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_FUNC);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_BACK_REF);
- gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK);
- gpu_state_print_fl(GL_STENCIL_BITS);
- gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE);
- gpu_state_print_fl(GL_STENCIL_FAIL);
- gpu_state_print_fl(GL_STENCIL_FUNC);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL);
- gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS);
- gpu_state_print_fl(GL_STENCIL_REF);
- gpu_state_print_fl(GL_STENCIL_TEST);
- gpu_state_print_fl(GL_STENCIL_VALUE_MASK);
- gpu_state_print_fl(GL_STENCIL_WRITEMASK);
- gpu_state_print_fl(GL_STEREO);
- gpu_state_print_fl(GL_SUBPIXEL_BITS);
- gpu_state_print_fl(GL_TEXTURE_1D);
- gpu_state_print_fl(GL_TEXTURE_2D);
- gpu_state_print_fl(GL_TEXTURE_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_1D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_2D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_3D);
- gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE);
- gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE);
- gpu_state_print_fl(GL_TEXTURE_CUBE_MAP);
- gpu_state_print_fl(GL_TEXTURE_GEN_Q);
- gpu_state_print_fl(GL_TEXTURE_GEN_R);
- gpu_state_print_fl(GL_TEXTURE_GEN_S);
- gpu_state_print_fl(GL_TEXTURE_GEN_T);
- gpu_state_print_fl(GL_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH);
- gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX);
- gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX);
- gpu_state_print_fl(GL_UNPACK_ALIGNMENT);
- gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT);
- gpu_state_print_fl(GL_UNPACK_LSB_FIRST);
- gpu_state_print_fl(GL_UNPACK_ROW_LENGTH);
- gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES);
- gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS);
- gpu_state_print_fl(GL_UNPACK_SKIP_ROWS);
- gpu_state_print_fl(GL_UNPACK_SWAP_BYTES);
- gpu_state_print_fl(GL_VERTEX_ARRAY);
- gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING);
- gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE);
- gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE);
- gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE);
- gpu_state_print_fl(GL_VIEWPORT);
- gpu_state_print_fl(GL_ZOOM_X);
- gpu_state_print_fl(GL_ZOOM_Y);
-}
-
-#undef gpu_state_print_fl
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 1fb1e239310..fb246aa802e 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -78,6 +78,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_material.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -137,7 +138,7 @@ void GPU_render_text(
else if (!col)
glColor3f(1.0f, 1.0f, 1.0f);
- glPushMatrix();
+ gpuPushMatrix();
/* get the tab width */
ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima);
@@ -155,12 +156,12 @@ void GPU_render_text(
character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
if (character == '\n') {
- glTranslatef(line_start, -line_height, 0.0f);
+ gpuTranslate2f(line_start, -line_height);
line_start = 0.0f;
continue;
}
else if (character == '\t') {
- glTranslatef(advance_tab, 0.0f, 0.0f);
+ gpuTranslate2f(advance_tab, 0.0f);
line_start -= advance_tab; /* so we can go back to the start of the line */
continue;
@@ -209,21 +210,22 @@ void GPU_render_text(
}
glEnd();
- glTranslatef(advance, 0.0f, 0.0f);
+ gpuTranslate2f(advance, 0.0f);
line_start -= advance; /* so we can go back to the start of the line */
}
- glPopMatrix();
+ gpuPopMatrix();
BKE_image_release_ibuf(ima, first_ibuf, NULL);
}
}
/* Checking powers of two for images since OpenGL ES requires it */
-
+#ifdef WITH_DDS
static bool is_power_of_2_resolution(int w, int h)
{
return is_power_of_2_i(w) && is_power_of_2_i(h);
}
+#endif
static bool is_over_resolution_limit(GLenum textarget, int w, int h)
{
@@ -418,7 +420,7 @@ void GPU_clear_tpage(bool force)
GTS.curima = NULL;
if (GTS.curtilemode != 0) {
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
}
GTS.curtilemode = 0;
@@ -602,10 +604,10 @@ int GPU_verify_image(
GTS.curtileYRep != GTS.tileYRep)
{
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
if (ima && (ima->tpageflag & IMA_TILES))
- glScalef(ima->xrep, ima->yrep, 1.0f);
+ glScalef(ima->xrep, ima->yrep, 0); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
}
@@ -1686,7 +1688,7 @@ void GPU_end_dupli_object(void)
}
void GPU_begin_object_materials(
- View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob,
+ View3D *v3d, RegionView3D *rv3d, Scene *scene, SceneLayer *sl, Object *ob,
bool glsl, bool *do_alpha_after)
{
Material *ma;
@@ -1725,8 +1727,10 @@ void GPU_begin_object_materials(
#ifdef WITH_GAMEENGINE
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
- ob = BKE_object_lod_matob_get(ob, scene);
+ ob = BKE_object_lod_matob_get(ob, sl);
}
+#else
+ UNUSED_VARS(sl);
#endif
/* initialize state */
@@ -2092,7 +2096,7 @@ void GPU_end_object_materials(void)
/* resetting the texture matrix after the scaling needed for tiled textures */
if (GTS.tilemode) {
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
}
}
@@ -2169,8 +2173,8 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
Lamp *la = base->object->data;
/* setup lamp transform */
- glPushMatrix();
- glLoadMatrixf((float *)viewmat);
+ gpuPushMatrix();
+ gpuLoadMatrix3D(viewmat);
/* setup light */
GPULightData light = {0};
@@ -2204,7 +2208,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
GPU_basic_shader_light_set(count, &light);
- glPopMatrix();
+ gpuPopMatrix();
count++;
if (count == 8)
@@ -2252,15 +2256,6 @@ static void gpu_multisample(bool enable)
void GPU_state_init(void)
{
- float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 };
- float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 };
-
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
- glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35);
- glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
-
GPU_default_lights();
GPU_disable_program_point_size();
@@ -2276,37 +2271,16 @@ void GPU_state_init(void)
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
- glDisable(GL_FOG);
- glDisable(GL_LIGHTING);
- glDisable(GL_COLOR_MATERIAL);
glDisable(GL_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- /* default disabled, enable should be local per function */
- glDisableClientState(GL_VERTEX_ARRAY);
- glDisableClientState(GL_NORMAL_ARRAY);
- glDisableClientState(GL_COLOR_ARRAY);
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
- glPixelTransferi(GL_RED_SCALE, 1);
- glPixelTransferi(GL_RED_BIAS, 0);
- glPixelTransferi(GL_GREEN_SCALE, 1);
- glPixelTransferi(GL_GREEN_BIAS, 0);
- glPixelTransferi(GL_BLUE_SCALE, 1);
- glPixelTransferi(GL_BLUE_BIAS, 0);
- glPixelTransferi(GL_ALPHA_SCALE, 1);
- glPixelTransferi(GL_ALPHA_BIAS, 0);
-
- glPixelTransferi(GL_DEPTH_BIAS, 0);
- glPixelTransferi(GL_DEPTH_SCALE, 1);
glDepthRange(0.0, 1.0);
glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
+ glLoadIdentity(); /* TEXTURE */
glMatrixMode(GL_MODELVIEW);
glFrontFace(GL_CCW);
@@ -2314,8 +2288,6 @@ void GPU_state_init(void)
glDisable(GL_CULL_FACE);
gpu_multisample(false);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
}
void GPU_enable_program_point_size(void)
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 1efc451f4a8..ce35c43bcec 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -32,9 +32,9 @@
#include "BKE_global.h"
-#include "GPU_debug.h"
-#include "GPU_glew.h"
+#include "GPU_batch.h"
#include "GPU_framebuffer.h"
+#include "GPU_matrix.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
@@ -131,14 +131,16 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo
}
}
- if (GPU_texture_depth(tex))
+ glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+ GG.currentfb = fb->object;
+
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex))
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ else if (GPU_texture_depth(tex))
attachment = GL_DEPTH_ATTACHMENT;
else
attachment = GL_COLOR_ATTACHMENT0 + slot;
- glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
- GG.currentfb = fb->object;
-
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
@@ -166,7 +168,11 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex)
GG.currentfb = fb->object;
}
- if (GPU_texture_depth(tex)) {
+ if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) {
+ fb->depthtex = NULL;
+ attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ }
+ else if (GPU_texture_depth(tex)) {
fb->depthtex = NULL;
attachment = GL_DEPTH_ATTACHMENT;
}
@@ -212,14 +218,9 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
glEnable(GL_MULTISAMPLE);
}
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
@@ -250,14 +251,9 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glDrawBuffers(numslots, attachments);
glReadBuffer(GL_COLOR_ATTACHMENT0 + slot);
- /* push matrices and set default viewport and matrix */
+ /* set default viewport */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
}
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
@@ -300,12 +296,6 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
- /* restore matrix */
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
-
/* restore attributes */
glPopAttrib();
}
@@ -379,20 +369,48 @@ void GPU_framebuffer_blur(
GPUFrameBuffer *fb, GPUTexture *tex,
GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
+ const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+ const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+ static VertexFormat format = {0};
+ static VertexBuffer vbo = {{0}};
+ static Batch batch = {{0}};
+
const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f};
const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
- int scale_uniform, texture_source_uniform;
if (!blur_shader)
return;
- scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU");
- texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource");
+ /* Preparing to draw quad */
+ if (format.attrib_ct == 0) {
+ unsigned int i = 0;
+ /* Vertex format */
+ unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+ unsigned int uvs = add_attrib(&format, "uvs", GL_FLOAT, 2, KEEP_FLOAT);
+
+ /* Vertices */
+ VertexBuffer_init_with_format(&vbo, &format);
+ VertexBuffer_allocate_data(&vbo, 36);
+
+ for (int j = 0; j < 3; ++j) {
+ setAttrib(&vbo, uvs, i, fullscreenuvs[j]); setAttrib(&vbo, pos, i++, fullscreencos[j]);
+ }
+ for (int j = 1; j < 4; ++j) {
+ setAttrib(&vbo, uvs, i, fullscreenuvs[j]); setAttrib(&vbo, pos, i++, fullscreencos[j]);
+ }
+
+ Batch_init(&batch, GL_TRIANGLES, &vbo, NULL);
+ }
- /* Blurring horizontally */
+ glDisable(GL_DEPTH_TEST);
+
+ /* Load fresh matrices */
+ gpuMatrixBegin3D(); /* TODO: finish 2D API */
+ /* Blurring horizontally */
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object);
@@ -401,51 +419,66 @@ void GPU_framebuffer_blur(
/* avoid warnings from texture binding */
GG.currentfb = blurfb->object;
- GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex);
glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex));
- /* Preparing to draw quad */
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glDisable(GL_DEPTH_TEST);
-
GPU_texture_bind(tex, 0);
- /* Drawing quad */
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ Batch_Uniform2f(&batch, "ScaleU", scaleh[0], scaleh[1]);
+ Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0);
+ Batch_draw(&batch);
/* Blurring vertically */
-
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
GG.currentfb = fb->object;
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev);
- GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex);
+
GPU_texture_bind(blurtex, 0);
- glBegin(GL_QUADS);
- glTexCoord2d(0, 0); glVertex2f(1, 1);
- glTexCoord2d(1, 0); glVertex2f(-1, 1);
- glTexCoord2d(1, 1); glVertex2f(-1, -1);
- glTexCoord2d(0, 1); glVertex2f(1, -1);
- glEnd();
+ /* Hack to make the following uniform stick */
+ Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR);
+ Batch_Uniform2f(&batch, "ScaleU", scalev[0], scalev[1]);
+ Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0);
+ Batch_draw(&batch);
- GPU_shader_unbind();
+ gpuMatrixEnd();
+}
+
+void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write, int write_slot, bool use_depth)
+{
+ GPUTexture *read_tex = (use_depth) ? fb_read->depthtex : fb_read->colortex[read_slot];
+ GPUTexture *write_tex = (use_depth) ? fb_write->depthtex : fb_write->colortex[write_slot];
+ int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex);
+ int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex);
+ int read_bind = GPU_texture_opengl_bindcode(read_tex);
+ int write_bind = GPU_texture_opengl_bindcode(write_tex);
+ const int read_w = GPU_texture_width(read_tex);
+ const int read_h = GPU_texture_height(read_tex);
+ const int write_w = GPU_texture_width(write_tex);
+ const int write_h = GPU_texture_height(write_tex);
+
+ /* read from multi-sample buffer */
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object);
+ glFramebufferTexture2D(
+ GL_READ_FRAMEBUFFER, read_attach,
+ GL_TEXTURE_2D, read_bind, 0);
+ BLI_assert(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ /* write into new single-sample buffer */
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object);
+ glFramebufferTexture2D(
+ GL_DRAW_FRAMEBUFFER, write_attach,
+ GL_TEXTURE_2D, write_bind, 0);
+ BLI_assert(glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+ glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h, (use_depth) ? GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT, GL_NEAREST);
+
+ /* Restore previous framebuffer */
+ glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
}
/* GPUOffScreen */
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
new file mode 100644
index 00000000000..ee0bcb83a6a
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -0,0 +1,475 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_lamp.c
+ * \ingroup gpu
+ *
+ * Manages Opengl lights.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_lamp_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_group.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_glew.h"
+#include "GPU_lamp.h"
+#include "GPU_material.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+
+#include "gpu_lamp_private.h"
+
+bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
+{
+ if (srl && srl->light_override)
+ return BKE_group_object_exists(srl->light_override, lamp->ob);
+ else if (ma && ma->group)
+ return BKE_group_object_exists(ma->group, lamp->ob);
+ else
+ return true;
+}
+
+static void gpu_lamp_calc_winmat(GPULamp *lamp)
+{
+ float temp, angle, pixsize, wsize;
+
+ if (lamp->type == LA_SUN) {
+ wsize = lamp->la->shadow_frustum_size;
+ orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
+ }
+ else if (lamp->type == LA_SPOT) {
+ angle = saacos(lamp->spotsi);
+ temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
+ pixsize = lamp->d / temp;
+ wsize = pixsize * 0.5f * lamp->size;
+ /* compute shadows according to X and Y scaling factors */
+ perspective_m4(
+ lamp->winmat,
+ -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
+ -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
+ lamp->d, lamp->clipend);
+ }
+}
+
+void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
+{
+ float mat[4][4];
+ float obmat_scale[3];
+
+ lamp->lay = lay;
+ lamp->hide = hide;
+
+ normalize_m4_m4_ex(mat, obmat, obmat_scale);
+
+ copy_v3_v3(lamp->vec, mat[2]);
+ copy_v3_v3(lamp->co, mat[3]);
+ copy_m4_m4(lamp->obmat, mat);
+ invert_m4_m4(lamp->imat, mat);
+
+ if (lamp->type == LA_SPOT) {
+ /* update spotlamp scale on X and Y axis */
+ lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
+ lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
+ }
+
+ if (GPU_lamp_has_shadow_buffer(lamp)) {
+ /* makeshadowbuf */
+ gpu_lamp_calc_winmat(lamp);
+ }
+}
+
+void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
+{
+ lamp->energy = energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = r;
+ lamp->col[1] = g;
+ lamp->col[2] = b;
+}
+
+void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
+ float coeff_const, float coeff_lin, float coeff_quad)
+{
+ lamp->dist = distance;
+ lamp->att1 = att1;
+ lamp->att2 = att2;
+ lamp->coeff_const = coeff_const;
+ lamp->coeff_lin = coeff_lin;
+ lamp->coeff_quad = coeff_quad;
+}
+
+void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
+{
+ lamp->spotsi = cosf(spotsize * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
+}
+
+static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
+{
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = la;
+
+ /* add_render_lamp */
+ lamp->mode = la->mode;
+ lamp->type = la->type;
+
+ lamp->energy = la->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
+
+ lamp->col[0] = la->r;
+ lamp->col[1] = la->g;
+ lamp->col[2] = la->b;
+
+ GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
+
+ lamp->spotsi = la->spotsize;
+ if (lamp->mode & LA_HALO)
+ if (lamp->spotsi > DEG2RADF(170.0f))
+ lamp->spotsi = DEG2RADF(170.0f);
+ lamp->spotsi = cosf(lamp->spotsi * 0.5f);
+ lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
+ lamp->k = la->k;
+
+ lamp->dist = la->dist;
+ lamp->falloff_type = la->falloff_type;
+ lamp->att1 = la->att1;
+ lamp->att2 = la->att2;
+ lamp->coeff_const = la->coeff_const;
+ lamp->coeff_lin = la->coeff_lin;
+ lamp->coeff_quad = la->coeff_quad;
+ lamp->curfalloff = la->curfalloff;
+
+ /* initshadowbuf */
+ lamp->bias = 0.02f * la->bias;
+ lamp->size = la->bufsize;
+ lamp->d = la->clipsta;
+ lamp->clipend = la->clipend;
+
+ /* arbitrary correction for the fact we do no soft transition */
+ lamp->bias *= 0.25f;
+}
+
+static void gpu_lamp_shadow_free(GPULamp *lamp)
+{
+ if (lamp->tex) {
+ GPU_texture_free(lamp->tex);
+ lamp->tex = NULL;
+ }
+ if (lamp->depthtex) {
+ GPU_texture_free(lamp->depthtex);
+ lamp->depthtex = NULL;
+ }
+ if (lamp->fb) {
+ GPU_framebuffer_free(lamp->fb);
+ lamp->fb = NULL;
+ }
+ if (lamp->blurtex) {
+ GPU_texture_free(lamp->blurtex);
+ lamp->blurtex = NULL;
+ }
+ if (lamp->blurfb) {
+ GPU_framebuffer_free(lamp->blurfb);
+ lamp->blurfb = NULL;
+ }
+}
+
+static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
+{
+ return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
+}
+
+GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re)
+{
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re))
+ return link->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ lamp->scene = scene;
+ lamp->ob = ob;
+ lamp->par = par;
+ lamp->la = ob->data;
+ lamp->re = re;
+
+ return lamp;
+}
+
+GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
+{
+ Lamp *la;
+ GPULamp *lamp;
+ LinkData *link;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = (GPULamp *)link->data;
+
+ if (lamp->par == par && lamp->scene == scene)
+ return link->data;
+ }
+
+ lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
+
+ link = MEM_callocN(sizeof(LinkData), "GPULampLink");
+ link->data = lamp;
+ BLI_addtail(&ob->gpulamp, link);
+
+ la = ob->data;
+ gpu_lamp_from_blender(scene, ob, par, la, lamp);
+
+ if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
+ (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
+ {
+ /* opengl */
+ lamp->fb = GPU_framebuffer_create();
+ if (!lamp->fb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ /* Shadow depth map */
+ lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->depthtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* Shadow color map */
+ lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* FBO and texture for blurring */
+ lamp->blurfb = GPU_framebuffer_create();
+ if (!lamp->blurfb) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
+ if (!lamp->blurtex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ /* we need to properly bind to test for completeness */
+ GPU_texture_bind_as_framebuffer(lamp->blurtex);
+
+ if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
+ }
+ else {
+ lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
+ if (!lamp->tex) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+
+ if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
+ gpu_lamp_shadow_free(lamp);
+ return lamp;
+ }
+ }
+
+ GPU_framebuffer_restore();
+
+ lamp->shadow_color[0] = la->shdwr;
+ lamp->shadow_color[1] = la->shdwg;
+ lamp->shadow_color[2] = la->shdwb;
+ }
+ else {
+ lamp->shadow_color[0] = 1.0;
+ lamp->shadow_color[1] = 1.0;
+ lamp->shadow_color[2] = 1.0;
+ }
+
+ return lamp;
+}
+
+void GPU_lamp_free(Object *ob)
+{
+ GPULamp *lamp;
+ LinkData *link;
+ LinkData *nlink;
+ Material *ma;
+
+ for (link = ob->gpulamp.first; link; link = link->next) {
+ lamp = link->data;
+
+ while (lamp->materials.first) {
+ nlink = lamp->materials.first;
+ ma = nlink->data;
+ BLI_freelinkN(&lamp->materials, nlink);
+
+ if (ma->gpumaterial.first)
+ GPU_material_free(&ma->gpumaterial);
+ }
+
+ gpu_lamp_shadow_free(lamp);
+
+ MEM_freeN(lamp);
+ }
+
+ BLI_freelistN(&ob->gpulamp);
+}
+
+bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
+{
+ return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
+ !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
+ lamp->tex && lamp->fb);
+}
+
+void GPU_lamp_update_buffer_mats(GPULamp *lamp)
+{
+ float rangemat[4][4], persmat[4][4];
+
+ /* initshadowbuf */
+ invert_m4_m4(lamp->viewmat, lamp->obmat);
+ normalize_v3(lamp->viewmat[0]);
+ normalize_v3(lamp->viewmat[1]);
+ normalize_v3(lamp->viewmat[2]);
+
+ /* makeshadowbuf */
+ mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
+
+ /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
+ unit_m4(rangemat);
+ rangemat[0][0] = 0.5f;
+ rangemat[1][1] = 0.5f;
+ rangemat[2][2] = 0.5f;
+ rangemat[3][0] = 0.5f;
+ rangemat[3][1] = 0.5f;
+ rangemat[3][2] = 0.5f;
+
+ mul_m4_m4m4(lamp->persmat, rangemat, persmat);
+}
+
+void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
+{
+ GPU_lamp_update_buffer_mats(lamp);
+
+ /* opengl */
+ glDisable(GL_SCISSOR_TEST);
+ GPU_texture_bind_as_framebuffer(lamp->tex);
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
+ GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
+
+ /* set matrices */
+ copy_m4_m4(viewmat, lamp->viewmat);
+ copy_m4_m4(winmat, lamp->winmat);
+ *winsize = lamp->size;
+}
+
+void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
+{
+ if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
+ GPU_shader_unbind();
+ GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
+ }
+
+ GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
+ GPU_framebuffer_restore();
+ glEnable(GL_SCISSOR_TEST);
+}
+
+int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
+{
+ return lamp->la->shadowmap_type;
+}
+
+int GPU_lamp_shadow_bind_code(GPULamp *lamp)
+{
+ return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
+}
+
+float *GPU_lamp_dynpersmat(GPULamp *lamp)
+{
+ return &lamp->dynpersmat[0][0];
+}
+
+int GPU_lamp_shadow_layer(GPULamp *lamp)
+{
+ if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
+ return lamp->lay;
+ else
+ return -1;
+}
diff --git a/source/blender/gpu/intern/gpu_lamp_private.h b/source/blender/gpu/intern/gpu_lamp_private.h
new file mode 100644
index 00000000000..ef71385e66d
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_lamp_private.h
@@ -0,0 +1,86 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Brecht Van Lommel, Clément Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_lamp_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_LAMP_PRIVATE_H__
+#define __GPU_LAMP_PRIVATE_H__
+
+#include "BLI_sys_types.h" /* for bool */
+
+struct GPULamp {
+ Scene *scene;
+ Object *ob;
+ Object *par;
+ Lamp *la;
+ struct RenderEngineType *re;
+
+ /* Old Viewport (pre-2.8) */
+ int type, mode, lay, hide;
+
+ float dynenergy, dyncol[3];
+ float energy, col[3];
+
+ float co[3], vec[3];
+ float dynco[3], dynvec[3];
+ float obmat[4][4];
+ float imat[4][4];
+ float dynimat[4][4];
+
+ float spotsi, spotbl, k;
+ float spotvec[2];
+ float dyndist, dynatt1, dynatt2;
+ float dist, att1, att2;
+ float coeff_const, coeff_lin, coeff_quad;
+ float shadow_color[3];
+
+ float bias, d, clipend;
+ int size;
+
+ int falloff_type;
+ struct CurveMapping *curfalloff;
+
+ float winmat[4][4];
+ float viewmat[4][4];
+ float persmat[4][4];
+ float dynpersmat[4][4];
+
+ GPUFrameBuffer *fb;
+ GPUFrameBuffer *blurfb;
+ GPUTexture *tex;
+ GPUTexture *depthtex;
+ GPUTexture *blurtex;
+
+ ListBase materials;
+
+ /* New viewport */
+ struct LampEngineData data;
+};
+
+#endif /* __GPU_LAMP_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 9e08f629bcb..153ae8ec8dc 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -60,11 +60,13 @@
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "gpu_codegen.h"
+#include "gpu_lamp_private.h"
#ifdef WITH_OPENSUBDIV
# include "BKE_DerivedMesh.h"
@@ -128,50 +130,6 @@ struct GPUMaterial {
bool is_opensubdiv;
};
-struct GPULamp {
- Scene *scene;
- Object *ob;
- Object *par;
- Lamp *la;
-
- int type, mode, lay, hide;
-
- float dynenergy, dyncol[3];
- float energy, col[3];
-
- float co[3], vec[3];
- float dynco[3], dynvec[3];
- float obmat[4][4];
- float imat[4][4];
- float dynimat[4][4];
-
- float spotsi, spotbl, k;
- float spotvec[2];
- float dyndist, dynatt1, dynatt2;
- float dist, att1, att2;
- float coeff_const, coeff_lin, coeff_quad;
- float shadow_color[3];
-
- float bias, d, clipend;
- int size;
-
- int falloff_type;
- struct CurveMapping *curfalloff;
-
- float winmat[4][4];
- float viewmat[4][4];
- float persmat[4][4];
- float dynpersmat[4][4];
-
- GPUFrameBuffer *fb;
- GPUFrameBuffer *blurfb;
- GPUTexture *tex;
- GPUTexture *depthtex;
- GPUTexture *blurtex;
-
- ListBase materials;
-};
-
/* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */
static void texture_rgb_blend(
GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg,
@@ -308,16 +266,6 @@ void GPU_material_free(ListBase *gpumaterial)
BLI_freelistN(gpumaterial);
}
-bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
-{
- if (srl && srl->light_override)
- return BKE_group_object_exists(srl->light_override, lamp->ob);
- else if (ma && ma->group)
- return BKE_group_object_exists(ma->group, lamp->ob);
- else
- return true;
-}
-
void GPU_material_bind(
GPUMaterial *material, int oblay, int viewlay, double time, int mipmap,
float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock)
@@ -1016,7 +964,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
{
- BaseLegacy *base;
+ Base *base;
Scene *sce_iter;
for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
@@ -2222,391 +2170,6 @@ void GPU_materials_free(void)
/* Lamps and shadow buffers */
-static void gpu_lamp_calc_winmat(GPULamp *lamp)
-{
- float temp, angle, pixsize, wsize;
-
- if (lamp->type == LA_SUN) {
- wsize = lamp->la->shadow_frustum_size;
- orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
- }
- else if (lamp->type == LA_SPOT) {
- angle = saacos(lamp->spotsi);
- temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
- pixsize = lamp->d / temp;
- wsize = pixsize * 0.5f * lamp->size;
- /* compute shadows according to X and Y scaling factors */
- perspective_m4(
- lamp->winmat,
- -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0],
- -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1],
- lamp->d, lamp->clipend);
- }
-}
-
-void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4])
-{
- float mat[4][4];
- float obmat_scale[3];
-
- lamp->lay = lay;
- lamp->hide = hide;
-
- normalize_m4_m4_ex(mat, obmat, obmat_scale);
-
- copy_v3_v3(lamp->vec, mat[2]);
- copy_v3_v3(lamp->co, mat[3]);
- copy_m4_m4(lamp->obmat, mat);
- invert_m4_m4(lamp->imat, mat);
-
- if (lamp->type == LA_SPOT) {
- /* update spotlamp scale on X and Y axis */
- lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2];
- lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2];
- }
-
- if (GPU_lamp_has_shadow_buffer(lamp)) {
- /* makeshadowbuf */
- gpu_lamp_calc_winmat(lamp);
- }
-}
-
-void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy)
-{
- lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = r;
- lamp->col[1] = g;
- lamp->col[2] = b;
-}
-
-void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2,
- float coeff_const, float coeff_lin, float coeff_quad)
-{
- lamp->dist = distance;
- lamp->att1 = att1;
- lamp->att2 = att2;
- lamp->coeff_const = coeff_const;
- lamp->coeff_lin = coeff_lin;
- lamp->coeff_quad = coeff_quad;
-}
-
-void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend)
-{
- lamp->spotsi = cosf(spotsize * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * spotblend;
-}
-
-static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp)
-{
- lamp->scene = scene;
- lamp->ob = ob;
- lamp->par = par;
- lamp->la = la;
-
- /* add_render_lamp */
- lamp->mode = la->mode;
- lamp->type = la->type;
-
- lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
-
- lamp->col[0] = la->r;
- lamp->col[1] = la->g;
- lamp->col[2] = la->b;
-
- GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat);
-
- lamp->spotsi = la->spotsize;
- if (lamp->mode & LA_HALO)
- if (lamp->spotsi > DEG2RADF(170.0f))
- lamp->spotsi = DEG2RADF(170.0f);
- lamp->spotsi = cosf(lamp->spotsi * 0.5f);
- lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend;
- lamp->k = la->k;
-
- lamp->dist = la->dist;
- lamp->falloff_type = la->falloff_type;
- lamp->att1 = la->att1;
- lamp->att2 = la->att2;
- lamp->coeff_const = la->coeff_const;
- lamp->coeff_lin = la->coeff_lin;
- lamp->coeff_quad = la->coeff_quad;
- lamp->curfalloff = la->curfalloff;
-
- /* initshadowbuf */
- lamp->bias = 0.02f * la->bias;
- lamp->size = la->bufsize;
- lamp->d = la->clipsta;
- lamp->clipend = la->clipend;
-
- /* arbitrary correction for the fact we do no soft transition */
- lamp->bias *= 0.25f;
-}
-
-static void gpu_lamp_shadow_free(GPULamp *lamp)
-{
- if (lamp->tex) {
- GPU_texture_free(lamp->tex);
- lamp->tex = NULL;
- }
- if (lamp->depthtex) {
- GPU_texture_free(lamp->depthtex);
- lamp->depthtex = NULL;
- }
- if (lamp->fb) {
- GPU_framebuffer_free(lamp->fb);
- lamp->fb = NULL;
- }
- if (lamp->blurtex) {
- GPU_texture_free(lamp->blurtex);
- lamp->blurtex = NULL;
- }
- if (lamp->blurfb) {
- GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb = NULL;
- }
-}
-
-static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
-{
- return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
-}
-
-GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
-{
- Lamp *la;
- GPULamp *lamp;
- LinkData *link;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = (GPULamp *)link->data;
-
- if (lamp->par == par && lamp->scene == scene)
- return link->data;
- }
-
- lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
-
- link = MEM_callocN(sizeof(LinkData), "GPULampLink");
- link->data = lamp;
- BLI_addtail(&ob->gpulamp, link);
-
- la = ob->data;
- gpu_lamp_from_blender(scene, ob, par, la, lamp);
-
- if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) ||
- (la->type == LA_SUN && (la->mode & LA_SHAD_RAY)))
- {
- /* opengl */
- lamp->fb = GPU_framebuffer_create();
- if (!lamp->fb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- /* Shadow depth map */
- lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->depthtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* Shadow color map */
- lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* FBO and texture for blurring */
- lamp->blurfb = GPU_framebuffer_create();
- if (!lamp->blurfb) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5);
- if (!lamp->blurtex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- /* we need to properly bind to test for completeness */
- GPU_texture_bind_as_framebuffer(lamp->blurtex);
-
- if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex);
- }
- else {
- lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL);
- if (!lamp->tex) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
-
- if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) {
- gpu_lamp_shadow_free(lamp);
- return lamp;
- }
- }
-
- GPU_framebuffer_restore();
-
- lamp->shadow_color[0] = la->shdwr;
- lamp->shadow_color[1] = la->shdwg;
- lamp->shadow_color[2] = la->shdwb;
- }
- else {
- lamp->shadow_color[0] = 1.0;
- lamp->shadow_color[1] = 1.0;
- lamp->shadow_color[2] = 1.0;
- }
-
- return lamp;
-}
-
-void GPU_lamp_free(Object *ob)
-{
- GPULamp *lamp;
- LinkData *link;
- LinkData *nlink;
- Material *ma;
-
- for (link = ob->gpulamp.first; link; link = link->next) {
- lamp = link->data;
-
- while (lamp->materials.first) {
- nlink = lamp->materials.first;
- ma = nlink->data;
- BLI_freelinkN(&lamp->materials, nlink);
-
- if (ma->gpumaterial.first)
- GPU_material_free(&ma->gpumaterial);
- }
-
- gpu_lamp_shadow_free(lamp);
-
- MEM_freeN(lamp);
- }
-
- BLI_freelistN(&ob->gpulamp);
-}
-
-bool GPU_lamp_has_shadow_buffer(GPULamp *lamp)
-{
- return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) &&
- !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) &&
- lamp->tex && lamp->fb);
-}
-
-void GPU_lamp_update_buffer_mats(GPULamp *lamp)
-{
- float rangemat[4][4], persmat[4][4];
-
- /* initshadowbuf */
- invert_m4_m4(lamp->viewmat, lamp->obmat);
- normalize_v3(lamp->viewmat[0]);
- normalize_v3(lamp->viewmat[1]);
- normalize_v3(lamp->viewmat[2]);
-
- /* makeshadowbuf */
- mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat);
-
- /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */
- unit_m4(rangemat);
- rangemat[0][0] = 0.5f;
- rangemat[1][1] = 0.5f;
- rangemat[2][2] = 0.5f;
- rangemat[3][0] = 0.5f;
- rangemat[3][1] = 0.5f;
- rangemat[3][2] = 0.5f;
-
- mul_m4_m4m4(lamp->persmat, rangemat, persmat);
-}
-
-void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4])
-{
- GPU_lamp_update_buffer_mats(lamp);
-
- /* opengl */
- glDisable(GL_SCISSOR_TEST);
- GPU_texture_bind_as_framebuffer(lamp->tex);
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE)
- GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE));
-
- /* set matrices */
- copy_m4_m4(viewmat, lamp->viewmat);
- copy_m4_m4(winmat, lamp->winmat);
- *winsize = lamp->size;
-}
-
-void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp)
-{
- if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
- GPU_shader_unbind();
- GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex);
- }
-
- GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex);
- GPU_framebuffer_restore();
- glEnable(GL_SCISSOR_TEST);
-}
-
-int GPU_lamp_shadow_buffer_type(GPULamp *lamp)
-{
- return lamp->la->shadowmap_type;
-}
-
-int GPU_lamp_shadow_bind_code(GPULamp *lamp)
-{
- return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1;
-}
-
-float *GPU_lamp_dynpersmat(GPULamp *lamp)
-{
- return &lamp->dynpersmat[0][0];
-}
-
-int GPU_lamp_shadow_layer(GPULamp *lamp)
-{
- if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW)))
- return lamp->lay;
- else
- return -1;
-}
-
GPUNodeLink *GPU_lamp_get_data(
GPUMaterial *mat, GPULamp *lamp,
GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy)
diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c
index 855ccaa4999..8f8754f612d 100644
--- a/source/blender/gpu/intern/gpu_matrix.c
+++ b/source/blender/gpu/intern/gpu_matrix.c
@@ -29,6 +29,7 @@
* \ingroup gpu
*/
+#define SUPPRESS_GENERIC_MATRIX_API
#include "GPU_matrix.h"
#include "BLI_math_matrix.h"
@@ -80,7 +81,7 @@ void gpuMatrixBegin2D(void)
state.mode = MATRIX_MODE_2D;
state.top = 0;
unit_m3(ModelView2D);
- gpuOrtho2D(-1.0f, +1.0f, -1.0f, +1.0f); // or identity?
+ unit_m3(Projection2D);
}
void gpuMatrixBegin3D(void)
@@ -88,21 +89,9 @@ void gpuMatrixBegin3D(void)
state.mode = MATRIX_MODE_3D;
state.top = 0;
unit_m4(ModelView3D);
- gpuOrtho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f); // or identity?
+ unit_m4(Projection3D);
}
-#if SUPPORT_LEGACY_MATRIX
-void gpuMatrixBegin3D_legacy(void)
-{
- /* copy top matrix from each legacy stack into new fresh stack */
- state.mode = MATRIX_MODE_3D;
- state.top = 0;
- state.dirty = true;
- glGetFloatv(GL_MODELVIEW_MATRIX, (float*)ModelView3D);
- glGetFloatv(GL_PROJECTION_MATRIX, (float*)Projection3D);
-}
-#endif
-
void gpuMatrixEnd(void)
{
state.mode = MATRIX_MODE_INACTIVE;
@@ -135,6 +124,14 @@ static void checkmat(cosnt float *m)
void gpuPushMatrix(void)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glPushMatrix();
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
BLI_assert(state.top < MATRIX_STACK_DEPTH);
state.top++;
@@ -146,6 +143,14 @@ void gpuPushMatrix(void)
void gpuPopMatrix(void)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glPopMatrix();
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode != MATRIX_MODE_INACTIVE);
BLI_assert(state.top > 0);
state.top--;
@@ -154,12 +159,47 @@ void gpuPopMatrix(void)
void gpuLoadMatrix3D(const float m[4][4])
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glLoadMatrixf((const float*) m);
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
copy_m4_m4(ModelView3D, m);
CHECKMAT(ModelView3D);
state.dirty = true;
}
+void gpuLoadProjectionMatrix3D(const float m[4][4])
+{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ GLenum mode;
+ glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
+ if (mode != GL_PROJECTION) {
+ glMatrixMode(GL_PROJECTION);
+ }
+
+ glLoadMatrixf((const float*) m);
+
+ if (mode != GL_PROJECTION_MATRIX) {
+ glMatrixMode(mode); /* restore */
+ }
+
+ state.dirty = true;
+ return;
+ }
+#endif
+
+ BLI_assert(state.mode == MATRIX_MODE_3D);
+ copy_m4_m4(Projection3D, m);
+ CHECKMAT(Projection3D);
+ state.dirty = true;
+}
+
void gpuLoadMatrix2D(const float m[3][3])
{
BLI_assert(state.mode == MATRIX_MODE_2D);
@@ -177,6 +217,11 @@ void gpuLoadIdentity(void)
case MATRIX_MODE_2D:
unit_m3(ModelView2D);
break;
+#if SUPPORT_LEGACY_MATRIX
+ case MATRIX_MODE_INACTIVE:
+ glLoadIdentity();
+ break;
+#endif
default:
BLI_assert(false);
}
@@ -185,6 +230,14 @@ void gpuLoadIdentity(void)
void gpuTranslate2f(float x, float y)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glTranslatef(x, y, 0.0f);
+ state.dirty = true;
+ return;
+ }
+#endif
+
Mat3 m;
unit_m3(m);
m[2][0] = x;
@@ -199,6 +252,14 @@ void gpuTranslate2fv(const float vec[2])
void gpuTranslate3f(float x, float y, float z)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glTranslatef(x, y, z);
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
#if 1
translate_m4(ModelView3D, x, y, z);
@@ -244,6 +305,12 @@ void gpuScaleUniform(float factor)
gpuMultMatrix2D(m);
break;
}
+#if SUPPORT_LEGACY_MATRIX
+ case MATRIX_MODE_INACTIVE:
+ glScalef(factor, factor, factor); /* always scale Z since we can't distinguish 2D from 3D */
+ state.dirty = true;
+ break;
+#endif
default:
BLI_assert(false);
}
@@ -251,6 +318,14 @@ void gpuScaleUniform(float factor)
void gpuScale2f(float x, float y)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glScalef(x, y, 1.0f);
+ state.dirty = true;
+ return;
+ }
+#endif
+
Mat3 m = {{0.0f}};
m[0][0] = x;
m[1][1] = y;
@@ -265,6 +340,14 @@ void gpuScale2fv(const float vec[2])
void gpuScale3f(float x, float y, float z)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glScalef(x, y, z);
+ state.dirty = true;
+ return;
+ }
+#endif
+
Mat4 m = {{0.0f}};
m[0][0] = x;
m[1][1] = y;
@@ -280,6 +363,14 @@ void gpuScale3fv(const float vec[3])
void gpuMultMatrix3D(const float m[4][4])
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glMultMatrixf((const float*) m);
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
mul_m4_m4_post(ModelView3D, m);
CHECKMAT(ModelView3D);
@@ -294,8 +385,35 @@ void gpuMultMatrix2D(const float m[3][3])
state.dirty = true;
}
+void gpuRotate2D(float deg)
+{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glRotatef(deg, 0.0f, 0.0f, 1.0f);
+ state.dirty = true;
+ return;
+ }
+#endif
+
+ BLI_assert(false); /* TODO: finish for MATRIX_MODE_2D */
+}
+
+void gpuRotate3f(float deg, float x, float y, float z)
+{
+ const float axis[3] = {x, y, z};
+ gpuRotate3fv(deg, axis);
+}
+
void gpuRotate3fv(float deg, const float axis[3])
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ glRotatef(deg, axis[0], axis[1], axis[2]);
+ state.dirty = true;
+ return;
+ }
+#endif
+
Mat4 m;
axis_angle_to_mat4(m, axis, DEG2RADF(deg));
gpuMultMatrix3D(m);
@@ -303,6 +421,21 @@ void gpuRotate3fv(float deg, const float axis[3])
void gpuRotateAxis(float deg, char axis)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ float a[3] = { 0.0f };
+ switch (axis) {
+ case 'X': a[0] = 1.0f; break;
+ case 'Y': a[1] = 1.0f; break;
+ case 'Z': a[2] = 1.0f; break;
+ default: BLI_assert(false); /* bad axis */
+ }
+ glRotatef(deg, a[0], a[1], a[2]);
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
#if 1 /* rotate_m4 works in place, right? */
rotate_m4(ModelView3D, axis, DEG2RADF(deg));
@@ -340,7 +473,7 @@ static void mat4_ortho_set(float m[4][4], float left, float right, float bottom,
state.dirty = true;
}
-static void mat4_frustum_set(float m[][4], float left, float right, float bottom, float top, float near, float far)
+static void mat4_frustum_set(float m[4][4], float left, float right, float bottom, float top, float near, float far)
{
m[0][0] = 2.0f * near / (right - left);
m[1][0] = 0.0f;
@@ -433,6 +566,26 @@ static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3
void gpuOrtho(float left, float right, float bottom, float top, float near, float far)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ GLenum mode;
+ glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
+ if (mode != GL_PROJECTION) {
+ glMatrixMode(GL_PROJECTION);
+ }
+
+ glLoadIdentity();
+ glOrtho(left, right, bottom, top, near, far);
+
+ if (mode != GL_PROJECTION_MATRIX) {
+ glMatrixMode(mode); /* restore */
+ }
+
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
mat4_ortho_set(Projection3D, left, right, bottom, top, near, far);
CHECKMAT(Projection3D);
@@ -441,6 +594,26 @@ void gpuOrtho(float left, float right, float bottom, float top, float near, floa
void gpuOrtho2D(float left, float right, float bottom, float top)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ GLenum mode;
+ glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
+ if (mode != GL_PROJECTION) {
+ glMatrixMode(GL_PROJECTION);
+ }
+
+ glLoadIdentity();
+ glOrtho(left, right, bottom, top, -1.0f, 1.0f);
+
+ if (mode != GL_PROJECTION_MATRIX) {
+ glMatrixMode(mode); /* restore */
+ }
+
+ state.dirty = true;
+ return;
+ }
+#endif
+
/* TODO: this function, but correct */
BLI_assert(state.mode == MATRIX_MODE_2D);
Mat4 m;
@@ -452,6 +625,26 @@ void gpuOrtho2D(float left, float right, float bottom, float top)
void gpuFrustum(float left, float right, float bottom, float top, float near, float far)
{
+#if SUPPORT_LEGACY_MATRIX
+ if (state.mode == MATRIX_MODE_INACTIVE) {
+ GLenum mode;
+ glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode);
+ if (mode != GL_PROJECTION) {
+ glMatrixMode(GL_PROJECTION);
+ }
+
+ glLoadIdentity();
+ glFrustum(left, right, bottom, top, near, far);
+
+ if (mode != GL_PROJECTION_MATRIX) {
+ glMatrixMode(mode); /* restore */
+ }
+
+ state.dirty = true;
+ return;
+ }
+#endif
+
BLI_assert(state.mode == MATRIX_MODE_3D);
mat4_frustum_set(Projection3D, left, right, bottom, top, near, far);
CHECKMAT(Projection3D);
@@ -481,19 +674,23 @@ void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY,
gpuTranslate3f(-eyeX, -eyeY, -eyeZ);
}
-void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3])
+void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3])
{
float v[4];
- mul_v4_m4v3(v, model, obj);
+ mul_v4_m4v3(v, model, world);
mul_m4_v4(proj, v);
+ if (v[3] != 0.0f) {
+ mul_v3_fl(v, 1.0f / v[3]);
+ }
+
win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f;
win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f;
win[2] = (v[2] + 1) * 0.5f;
}
-bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3])
+bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3])
{
float pm[4][4];
float in[4];
@@ -502,6 +699,7 @@ bool gpuUnProject(const float win[3], const float model[4][4], const float proj[
mul_m4_m4m4(pm, proj, model);
if (!invert_m4(pm)) {
+ zero_v3(world);
return false;
}
@@ -522,19 +720,12 @@ bool gpuUnProject(const float win[3], const float model[4][4], const float proj[
mul_v4_m4v3(out, pm, in);
if (out[3] == 0.0f) {
+ copy_v3_v3(world, out);
return false;
}
- else {
- out[0] /= out[3];
- out[1] /= out[3];
- out[2] /= out[3];
-
- obj[0] = out[0];
- obj[1] = out[1];
- obj[2] = out[2];
- return true;
- }
+ mul_v3_v3fl(world, out, 1.0f / out[3]);
+ return true;
}
const float *gpuGetModelViewMatrix3D(float m[4][4])
@@ -579,38 +770,33 @@ const float *gpuGetProjectionMatrix3D(float m[4][4])
BLI_assert(state.mode == MATRIX_MODE_3D);
if (m) {
- copy_m4_m4(m, ModelView3D);
+ copy_m4_m4(m, Projection3D);
return (const float*)m;
}
else {
- return (const float*)ModelView3D;
+ return (const float*)Projection3D;
}
}
const float *gpuGetModelViewProjectionMatrix3D(float m[4][4])
{
+ if (m == NULL) {
+ static Mat4 temp;
+ m = temp;
+ }
+
#if SUPPORT_LEGACY_MATRIX
if (state.mode == MATRIX_MODE_INACTIVE) {
- if (m == NULL) {
- static Mat4 temp;
- m = temp;
- }
-
Mat4 proj;
- glGetFloatv(GL_MODELVIEW_MATRIX, (float*)proj);
- glGetFloatv(GL_PROJECTION_MATRIX, (float*)m);
- mul_m4_m4_post(m, proj);
+ glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m);
+ glGetFloatv(GL_PROJECTION_MATRIX, (float*)proj);
+ mul_m4_m4_pre(m, proj);
return (const float*)m;
}
#endif
BLI_assert(state.mode == MATRIX_MODE_3D);
- if (m == NULL) {
- static Mat4 temp;
- m = temp;
- }
-
mul_m4_m4m4(m, Projection3D, ModelView3D);
return (const float*)m;
}
@@ -692,6 +878,27 @@ void gpuBindMatrices(GLuint program)
glUniformMatrix3fv(loc_N, 1, GL_FALSE, gpuGetNormalMatrix(NULL));
}
+ /* also needed by material.glsl
+ * - ProjectionMatrixInverse
+ * - ModelViewMatrixInverse
+ */
+ GLint loc_MV_inv = glGetUniformLocation(program, "ModelViewInverseMatrix");
+ GLint loc_P_inv = glGetUniformLocation(program, "ProjectionInverseMatrix");
+
+ if (loc_MV_inv != -1) {
+ Mat4 m;
+ gpuGetModelViewMatrix3D(m);
+ invert_m4(m);
+ glUniformMatrix4fv(loc_MV_inv, 1, GL_FALSE, (const float*) m);
+ }
+
+ if (loc_P_inv != -1) {
+ Mat4 m;
+ gpuGetProjectionMatrix3D(m);
+ invert_m4(m);
+ glUniformMatrix4fv(loc_P_inv, 1, GL_FALSE, (const float*) m);
+ }
+
state.dirty = false;
}
@@ -699,11 +906,3 @@ bool gpuMatricesDirty(void)
{
return state.dirty;
}
-
-#if SUPPORT_LEGACY_MATRIX
-void gpuMatrixUpdate_legacy(void)
-{
- BLI_assert(state.mode == MATRIX_MODE_INACTIVE);
- state.dirty = true;
-}
-#endif
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 58582232cd5..c384fa01fc6 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -29,109 +29,86 @@
* Interface for accessing gpu-related methods for selection. The semantics will be
* similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility.
*/
+#include <stdlib.h>
+
#include "GPU_select.h"
#include "GPU_extensions.h"
#include "GPU_glew.h"
-
+
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
#include "BLI_utildefines.h"
-/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
-#define ALLOC_QUERIES 200
-
-typedef struct GPUQueryState {
+#include "gpu_select_private.h"
+
+/* Internal algorithm used */
+enum {
+ /** GL_SELECT, legacy OpenGL selection */
+ ALGO_GL_LEGACY = 1,
+ /** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c`
+ * Only sets 4th component (ID) correctly. */
+ ALGO_GL_QUERY = 2,
+ /** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c`
+ * Only sets 4th component (ID) correctly. */
+ ALGO_GL_PICK = 3,
+};
+
+typedef struct GPUSelectState {
/* To ignore selection id calls when not initialized */
bool select_is_active;
- /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
- bool query_issued;
- /* array holding the OpenGL query identifiers */
- unsigned int *queries;
- /* array holding the id corresponding to each query */
- unsigned int *id;
- /* number of queries in *queries and *id */
- unsigned int num_of_queries;
- /* index to the next query to start */
- unsigned int active_query;
/* flag to cache user preference for occlusion based selection */
bool use_gpu_select;
- /* cache on initialization */
- unsigned int *buffer;
- /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
- unsigned int bufsize;
/* mode of operation */
char mode;
- unsigned int index;
- int oldhits;
-} GPUQueryState;
+ /* internal algorithm for selection */
+ char algorithm;
+ /* allow GPU_select_begin/end without drawing */
+ bool use_cache;
+} GPUSelectState;
-static GPUQueryState g_query_state = {0};
+static GPUSelectState g_select_state = {0};
/**
* initialize and provide buffer for results
*/
-void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits)
+void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits)
{
- g_query_state.select_is_active = true;
- g_query_state.query_issued = false;
- g_query_state.active_query = 0;
- g_query_state.use_gpu_select = GPU_select_query_check_active();
- g_query_state.num_of_queries = 0;
- g_query_state.bufsize = bufsize;
- g_query_state.buffer = buffer;
- g_query_state.mode = mode;
- g_query_state.index = 0;
- g_query_state.oldhits = oldhits;
+ g_select_state.select_is_active = true;
+ g_select_state.use_gpu_select = GPU_select_query_check_active();
+ g_select_state.mode = mode;
- if (!g_query_state.use_gpu_select) {
- glSelectBuffer(bufsize, (GLuint *)buffer);
- glRenderMode(GL_SELECT);
- glInitNames();
- glPushName(-1);
+ if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) {
+ g_select_state.algorithm = ALGO_GL_PICK;
+ }
+ else if (!g_select_state.use_gpu_select) {
+ g_select_state.algorithm = ALGO_GL_LEGACY;
}
else {
- float viewport[4];
-
- g_query_state.num_of_queries = ALLOC_QUERIES;
-
- g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries");
- g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
- glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
-
- glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
- /* disable writing to the framebuffer */
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- /* In order to save some fill rate we minimize the viewport using rect.
- * We need to get the region of the scissor so that our geometry doesn't
- * get rejected before the depth test. Should probably cull rect against
- * scissor for viewport but this is a rare case I think */
- glGetFloatv(GL_SCISSOR_BOX, viewport);
- if (!input || input->xmin == input->xmax) {
- glViewport(viewport[0], viewport[1], 24, 24);
- }
- else {
- glViewport(viewport[0], viewport[1], (int)(input->xmax - input->xmin), (int)(input->ymax - input->ymin));
- }
+ g_select_state.algorithm = ALGO_GL_QUERY;
+ }
- /* occlusion queries operates on fragments that pass tests and since we are interested on all
- * objects in the view frustum independently of their order, we need to disable the depth test */
- if (mode == GPU_SELECT_ALL) {
- glDisable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_LEGACY:
+ {
+ g_select_state.use_cache = false;
+ glSelectBuffer(bufsize, (GLuint *)buffer);
+ glRenderMode(GL_SELECT);
+ glInitNames();
+ glPushName(-1);
+ break;
}
- else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
- glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_TRUE);
- glDepthFunc(GL_LEQUAL);
+ case ALGO_GL_QUERY:
+ {
+ g_select_state.use_cache = false;
+ gpu_select_query_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode, oldhits);
+ break;
}
- else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
- glEnable(GL_DEPTH_TEST);
- glDepthMask(GL_FALSE);
- glDepthFunc(GL_EQUAL);
+ default: /* ALGO_GL_PICK */
+ {
+ gpu_select_pick_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode);
+ break;
}
}
}
@@ -146,41 +123,24 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
bool GPU_select_load_id(unsigned int id)
{
/* if no selection mode active, ignore */
- if (!g_query_state.select_is_active)
+ if (!g_select_state.select_is_active)
return true;
- if (!g_query_state.use_gpu_select) {
- glLoadName(id);
- }
- else {
- if (g_query_state.query_issued) {
- glEndQuery(GL_SAMPLES_PASSED);
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_LEGACY:
+ {
+ glLoadName(id);
+ return true;
}
- /* if required, allocate extra queries */
- if (g_query_state.active_query == g_query_state.num_of_queries) {
- g_query_state.num_of_queries += ALLOC_QUERIES;
- g_query_state.queries = MEM_reallocN(g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries));
- g_query_state.id = MEM_reallocN(g_query_state.id, g_query_state.num_of_queries * sizeof(*g_query_state.id));
- glGenQueries(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]);
+ case ALGO_GL_QUERY:
+ {
+ return gpu_select_query_load_id(id);
}
-
- glBeginQuery(GL_SAMPLES_PASSED, g_query_state.queries[g_query_state.active_query]);
- g_query_state.id[g_query_state.active_query] = id;
- g_query_state.active_query++;
- g_query_state.query_issued = true;
-
- if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
- if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) {
- g_query_state.index++;
- return true;
- }
- else {
- return false;
- }
+ default: /* ALGO_GL_PICK */
+ {
+ return gpu_select_pick_load_id(id);
}
}
-
- return true;
}
/**
@@ -191,59 +151,27 @@ bool GPU_select_load_id(unsigned int id)
unsigned int GPU_select_end(void)
{
unsigned int hits = 0;
- if (!g_query_state.use_gpu_select) {
- glPopName();
- hits = glRenderMode(GL_RENDER);
- }
- else {
- int i;
- if (g_query_state.query_issued) {
- glEndQuery(GL_SAMPLES_PASSED);
+ switch (g_select_state.algorithm) {
+ case ALGO_GL_LEGACY:
+ {
+ glPopName();
+ hits = glRenderMode(GL_RENDER);
+ break;
}
-
- for (i = 0; i < g_query_state.active_query; i++) {
- unsigned int result;
- glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
- if (result > 0) {
- if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
- int maxhits = g_query_state.bufsize / 4;
-
- if (hits < maxhits) {
- g_query_state.buffer[hits * 4] = 1;
- g_query_state.buffer[hits * 4 + 1] = 0xFFFF;
- g_query_state.buffer[hits * 4 + 2] = 0xFFFF;
- g_query_state.buffer[hits * 4 + 3] = g_query_state.id[i];
-
- hits++;
- }
- else {
- hits = -1;
- break;
- }
- }
- else {
- int j;
- /* search in buffer and make selected object first */
- for (j = 0; j < g_query_state.oldhits; j++) {
- if (g_query_state.buffer[j * 4 + 3] == g_query_state.id[i]) {
- g_query_state.buffer[j * 4 + 1] = 0;
- g_query_state.buffer[j * 4 + 2] = 0;
- }
- }
- break;
- }
- }
+ case ALGO_GL_QUERY:
+ {
+ hits = gpu_select_query_end();
+ break;
+ }
+ default: /* ALGO_GL_PICK */
+ {
+ hits = gpu_select_pick_end();
+ break;
}
-
- glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries);
- MEM_freeN(g_query_state.queries);
- MEM_freeN(g_query_state.id);
- glPopAttrib();
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
- g_query_state.select_is_active = false;
+ g_select_state.select_is_active = false;
return hits;
}
@@ -253,10 +181,43 @@ unsigned int GPU_select_end(void)
*/
bool GPU_select_query_check_active(void)
{
- return ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) ||
- ((U.gpu_select_method == USER_SELECT_AUTO) &&
- (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) ||
- /* unsupported by nouveau, gallium 0.4, see: T47940 */
- GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE))));
+ return ELEM(U.gpu_select_method, USER_SELECT_USE_OCCLUSION_QUERY, USER_SELECT_AUTO);
+}
+
+/* ----------------------------------------------------------------------------
+ * Caching
+ *
+ * Support multiple begin/end's as long as they are within the initial region.
+ * Currently only used by ALGO_GL_PICK.
+ */
+
+void GPU_select_cache_begin(void)
+{
+ /* validate on GPU_select_begin, clear if not supported */
+ BLI_assert(g_select_state.use_cache == false);
+ g_select_state.use_cache = true;
+ if (g_select_state.algorithm == ALGO_GL_PICK) {
+ gpu_select_pick_cache_begin();
+ }
+}
+
+void GPU_select_cache_load_id(void)
+{
+ BLI_assert(g_select_state.use_cache == true);
+ if (g_select_state.algorithm == ALGO_GL_PICK) {
+ gpu_select_pick_cache_load_id();
+ }
+}
+
+void GPU_select_cache_end(void)
+{
+ if (g_select_state.algorithm == ALGO_GL_PICK) {
+ gpu_select_pick_cache_end();
+ }
+ g_select_state.use_cache = false;
+}
+bool GPU_select_is_cached(void)
+{
+ return g_select_state.use_cache && gpu_select_pick_is_cached();
}
diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c
new file mode 100644
index 00000000000..780ffd82671
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_select_pick.c
@@ -0,0 +1,740 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_select_pick.c
+ * \ingroup gpu
+ *
+ * Custom select code for picking small regions (not efficient for large regions).
+ * `gpu_select_pick_*` API.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+#include "GPU_select.h"
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_rect.h"
+#include "BLI_listbase.h"
+#include "BLI_math_vector.h"
+#include "BLI_utildefines.h"
+
+#include "gpu_select_private.h"
+
+#include "BLI_strict_flags.h"
+
+/* #define DEBUG_PRINT */
+
+/* Alloc number for depths */
+#define ALLOC_DEPTHS 200
+
+/* Z-depth of cleared depth buffer */
+#define DEPTH_MAX 0xffffffff
+
+/* ----------------------------------------------------------------------------
+ * SubRectStride
+ */
+
+/* For looping over a sub-region of a rect, could be moved into 'rct.c'*/
+typedef struct SubRectStride {
+ unsigned int start; /* start here */
+ unsigned int span; /* read these */
+ unsigned int span_len; /* len times (read span 'len' times). */
+ unsigned int skip; /* skip those */
+} SubRectStride;
+
+/* we may want to change back to float if uint isn't well supported */
+typedef unsigned int depth_t;
+
+/**
+ * Calculate values needed for looping over a sub-region (smaller buffer within a larger buffer).
+ *
+ * 'src' must be bigger than 'dst'.
+ */
+static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRectStride *r_sub)
+{
+ const int src_x = BLI_rcti_size_x(src);
+ // const int src_y = BLI_rcti_size_y(src);
+ const int dst_x = BLI_rcti_size_x(dst);
+ const int dst_y = BLI_rcti_size_y(dst);
+ const int x = dst->xmin - src->xmin;
+ const int y = dst->ymin - src->ymin;
+
+ BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin &&
+ src->ymax >= dst->ymax && src->ymax >= dst->ymax);
+ BLI_assert(x >= 0 && y >= 0);
+
+ r_sub->start = (unsigned int)((src_x * y) + x);
+ r_sub->span = (unsigned int)dst_x;
+ r_sub->span_len = (unsigned int)dst_y;
+ r_sub->skip = (unsigned int)(src_x - dst_x);
+}
+
+/**
+ * Ignore depth clearing as a change,
+ * only check if its been changed _and_ filled in (ignore clearing since XRAY does this).
+ */
+BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr)
+{
+ return (*prev != *curr) && (*curr != DEPTH_MAX);
+}
+
+/* ----------------------------------------------------------------------------
+ * DepthBufCache
+ *
+ * Result of reading glReadPixels,
+ * use for both cache and non-cached storage.
+ */
+
+/* store result of glReadPixels */
+typedef struct DepthBufCache {
+ struct DepthBufCache *next, *prev;
+ unsigned int id;
+ depth_t buf[0];
+} DepthBufCache;
+
+static DepthBufCache *depth_buf_malloc(unsigned int rect_len)
+{
+ DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__);
+ rect->id = SELECT_ID_NONE;
+ return rect;
+}
+
+static bool depth_buf_rect_depth_any(
+ const DepthBufCache *rect_depth,
+ unsigned int rect_len)
+{
+ const depth_t *curr = rect_depth->buf;
+ for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ if (*curr != DEPTH_MAX) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool depth_buf_subrect_depth_any(
+ const DepthBufCache *rect_depth,
+ const SubRectStride *sub_rect)
+{
+ const depth_t *curr = rect_depth->buf + sub_rect->start;
+ for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ const depth_t *curr_end = curr + sub_rect->span;
+ for (; curr < curr_end; curr++, curr++) {
+ if (*curr != DEPTH_MAX) {
+ return true;
+ }
+ }
+ curr += sub_rect->skip;
+ }
+ return false;
+}
+
+static bool depth_buf_rect_depth_any_filled(
+ const DepthBufCache *rect_prev, const DepthBufCache *rect_curr,
+ unsigned int rect_len)
+{
+#if 0
+ return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0;
+#else
+ const depth_t *prev = rect_prev->buf;
+ const depth_t *curr = rect_curr->buf;
+ for (unsigned int i = 0; i < rect_len; i++, curr++, prev++) {
+ if (depth_is_filled(prev, curr)) {
+ return true;
+ }
+ }
+ return false;
+#endif
+}
+
+/**
+ * Both buffers are the same size, just check if the sub-rect contains any differences.
+ */
+static bool depth_buf_subrect_depth_any_filled(
+ const DepthBufCache *rect_src, const DepthBufCache *rect_dst,
+ const SubRectStride *sub_rect)
+{
+ /* same as above but different rect sizes */
+ const depth_t *prev = rect_src->buf + sub_rect->start;
+ const depth_t *curr = rect_dst->buf + sub_rect->start;
+ for (unsigned int i = 0; i < sub_rect->span_len; i++) {
+ const depth_t *curr_end = curr + sub_rect->span;
+ for (; curr < curr_end; prev++, curr++) {
+ if (depth_is_filled(prev, curr)) {
+ return true;
+ }
+ }
+ prev += sub_rect->skip;
+ curr += sub_rect->skip;
+ }
+ return false;
+}
+
+/* ----------------------------------------------------------------------------
+ * DepthID
+ *
+ * Internal structure for storing hits.
+ */
+
+typedef struct DepthID {
+ unsigned int id;
+ depth_t depth;
+} DepthID;
+
+static int depth_id_cmp(const void *v1, const void *v2)
+{
+ const DepthID *d1 = v1, *d2 = v2;
+ if (d1->id < d2->id) {
+ return -1;
+ }
+ else if (d1->id > d2->id) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static int depth_cmp(const void *v1, const void *v2)
+{
+ const DepthID *d1 = v1, *d2 = v2;
+ if (d1->depth < d2->depth) {
+ return -1;
+ }
+ else if (d1->depth > d2->depth) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* depth sorting */
+typedef struct GPUPickState {
+ /* cache on initialization */
+ unsigned int (*buffer)[4];
+
+ /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
+ unsigned int bufsize;
+ /* mode of operation */
+ char mode;
+
+ /* OpenGL drawing, never use when (is_cached == true). */
+ struct {
+ /* The current depth, accumulated as we draw */
+ DepthBufCache *rect_depth;
+ /* Scratch buffer, avoid allocs every time (when not caching) */
+ DepthBufCache *rect_depth_test;
+
+ /* Pass to glReadPixels (x, y, w, h) */
+ int clip_readpixels[4];
+
+ /* Set after first draw */
+ bool is_init;
+ unsigned int prev_id;
+ } gl;
+
+ /* src: data stored in 'cache' and 'gl',
+ * dst: use when cached region is smaller (where src -> dst isn't 1:1) */
+ struct {
+ rcti clip_rect;
+ unsigned int rect_len;
+ } src, dst;
+
+ /* Store cache between `GPU_select_cache_begin/end` */
+ bool use_cache;
+ bool is_cached;
+ struct {
+ /* Cleanup used for iterating over both source and destination buffers:
+ * src.clip_rect -> dst.clip_rect */
+ SubRectStride sub_rect;
+
+ /* List of DepthBufCache, sized of 'src.clip_rect' */
+ ListBase bufs;
+ } cache;
+
+ /* Pickign methods */
+ union {
+ /* GPU_SELECT_PICK_ALL */
+ struct {
+ DepthID *hits;
+ unsigned int hits_len;
+ unsigned int hits_len_alloc;
+ } all;
+
+ /* GPU_SELECT_PICK_NEAREST */
+ struct {
+ unsigned int *rect_id;
+ } nearest;
+ };
+} GPUPickState;
+
+
+static GPUPickState g_pick_state = {0};
+
+void gpu_select_pick_begin(
+ unsigned int (*buffer)[4], unsigned int bufsize,
+ const rcti *input, char mode)
+{
+ GPUPickState *ps = &g_pick_state;
+
+#ifdef DEBUG_PRINT
+ printf("%s: mode=%d, use_cache=%d, is_cache=%d\n", __func__, mode, ps->use_cache, ps->is_cached);
+#endif
+
+ ps->bufsize = bufsize;
+ ps->buffer = buffer;
+ ps->mode = mode;
+
+ const unsigned int rect_len = (unsigned int)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
+ ps->dst.clip_rect = *input;
+ ps->dst.rect_len = rect_len;
+
+ /* Restrict OpenGL operations for when we don't have cache */
+ if (ps->is_cached == false) {
+
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ /* disable writing to the framebuffer */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+
+ if (mode == GPU_SELECT_PICK_ALL) {
+ glDepthFunc(GL_ALWAYS);
+ }
+ else {
+ glDepthFunc(GL_LEQUAL);
+ }
+
+ float viewport[4];
+ glGetFloatv(GL_SCISSOR_BOX, viewport);
+
+ ps->src.clip_rect = *input;
+ ps->src.rect_len = rect_len;
+
+ ps->gl.clip_readpixels[0] = (int)viewport[0];
+ ps->gl.clip_readpixels[1] = (int)viewport[1];
+ ps->gl.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect);
+ ps->gl.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect);
+
+ glViewport(UNPACK4(ps->gl.clip_readpixels));
+
+ /* It's possible we don't want to clear depth buffer,
+ * so existing elements are masked by current z-buffer. */
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ /* scratch buffer (read new values here) */
+ ps->gl.rect_depth_test = depth_buf_malloc(rect_len);
+ ps->gl.rect_depth = depth_buf_malloc(rect_len);
+
+ /* set initial 'far' value */
+#if 0
+ glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf);
+#else
+ for (unsigned int i = 0; i < rect_len; i++) {
+ ps->gl.rect_depth->buf[i] = DEPTH_MAX;
+ }
+#endif
+
+ ps->gl.is_init = false;
+ ps->gl.prev_id = 0;
+ }
+ else {
+ /* Using cache (ps->is_cached == true) */
+ /* src.clip_rect -> dst.clip_rect */
+ rect_subregion_stride_calc(&ps->src.clip_rect, &ps->dst.clip_rect, &ps->cache.sub_rect);
+ BLI_assert(ps->gl.rect_depth == NULL);
+ BLI_assert(ps->gl.rect_depth_test == NULL);
+ }
+
+ if (mode == GPU_SELECT_PICK_ALL) {
+ ps->all.hits = MEM_mallocN(sizeof(*ps->all.hits) * ALLOC_DEPTHS, __func__);
+ ps->all.hits_len = 0;
+ ps->all.hits_len_alloc = ALLOC_DEPTHS;
+ }
+ else {
+ /* Set to 0xff for SELECT_ID_NONE */
+ ps->nearest.rect_id = MEM_mallocN(sizeof(unsigned int) * ps->dst.rect_len, __func__);
+ memset(ps->nearest.rect_id, 0xff, sizeof(unsigned int) * ps->dst.rect_len);
+ }
+}
+
+/**
+ * Given 2x depths, we know are different - update the depth information
+ * use for both cached/uncached depth buffers.
+ */
+static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr)
+{
+ GPUPickState *ps = &g_pick_state;
+ const unsigned int id = rect_curr->id;
+ /* find the best depth for this pass and store in 'all.hits' */
+ depth_t depth_best = DEPTH_MAX;
+
+#define EVAL_TEST() \
+ if (depth_best > *curr) { \
+ depth_best = *curr; \
+ } ((void)0)
+
+ if (ps->is_cached == false) {
+ const depth_t *curr = rect_curr->buf;
+ BLI_assert(ps->src.rect_len == ps->dst.rect_len);
+ const unsigned int rect_len = ps->src.rect_len;
+ for (unsigned int i = 0; i < rect_len; i++, curr++) {
+ EVAL_TEST();
+ }
+ }
+ else {
+ /* same as above but different rect sizes */
+ const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
+ for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ const depth_t *curr_end = curr + ps->cache.sub_rect.span;
+ for (; curr < curr_end; curr++) {
+ EVAL_TEST();
+ }
+ curr += ps->cache.sub_rect.skip;
+ }
+ }
+
+#undef EVAL_TEST
+
+ /* ensure enough space */
+ if (UNLIKELY(ps->all.hits_len == ps->all.hits_len_alloc)) {
+ ps->all.hits_len_alloc += ALLOC_DEPTHS;
+ ps->all.hits = MEM_reallocN(ps->all.hits, ps->all.hits_len_alloc * sizeof(*ps->all.hits));
+ }
+ DepthID *d = &ps->all.hits[ps->all.hits_len++];
+ d->id = id;
+ d->depth = depth_best;
+}
+
+static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr)
+{
+ GPUPickState *ps = &g_pick_state;
+ const unsigned int id = rect_curr->id;
+ /* keep track each pixels ID in 'nearest.rect_id' */
+ if (id != SELECT_ID_NONE) {
+ unsigned int *id_ptr = ps->nearest.rect_id;
+
+ /* Check against DEPTH_MAX because XRAY will clear the buffer,
+ * so previously set values will become unset.
+ * In this case just leave those id's left as-is. */
+#define EVAL_TEST() \
+ if (depth_is_filled(prev, curr)) { \
+ *id_ptr = id; \
+ } ((void)0)
+
+ if (ps->is_cached == false) {
+ const depth_t *prev = rect_prev->buf;
+ const depth_t *curr = rect_curr->buf;
+ BLI_assert(ps->src.rect_len == ps->dst.rect_len);
+ const unsigned int rect_len = ps->src.rect_len;
+ for (unsigned int i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) {
+ EVAL_TEST();
+ }
+ }
+ else {
+ /* same as above but different rect sizes */
+ const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start;
+ const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start;
+ for (unsigned int i = 0; i < ps->cache.sub_rect.span_len; i++) {
+ const depth_t *curr_end = curr + ps->cache.sub_rect.span;
+ for (; curr < curr_end; prev++, curr++, id_ptr++) {
+ EVAL_TEST();
+ }
+ prev += ps->cache.sub_rect.skip;
+ curr += ps->cache.sub_rect.skip;
+ }
+ }
+
+#undef EVAL_TEST
+ }
+}
+
+
+bool gpu_select_pick_load_id(unsigned int id)
+{
+ GPUPickState *ps = &g_pick_state;
+ if (ps->gl.is_init) {
+ const unsigned int rect_len = ps->src.rect_len;
+ glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth_test->buf);
+ /* perform initial check since most cases the array remains unchanged */
+
+ bool do_pass = false;
+ if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ if (depth_buf_rect_depth_any(ps->gl.rect_depth_test, rect_len)) {
+ ps->gl.rect_depth_test->id = ps->gl.prev_id;
+ gpu_select_load_id_pass_all(ps->gl.rect_depth_test);
+ do_pass = true;
+ }
+ }
+ else {
+ if (depth_buf_rect_depth_any_filled(ps->gl.rect_depth, ps->gl.rect_depth_test, rect_len)) {
+ ps->gl.rect_depth_test->id = ps->gl.prev_id;
+ gpu_select_load_id_pass_nearest(ps->gl.rect_depth, ps->gl.rect_depth_test);
+ do_pass = true;
+ }
+ }
+
+ if (do_pass) {
+ /* Store depth in cache */
+ if (ps->use_cache) {
+ BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth);
+ ps->gl.rect_depth = depth_buf_malloc(ps->src.rect_len);
+ }
+
+ SWAP(DepthBufCache *, ps->gl.rect_depth, ps->gl.rect_depth_test);
+
+ if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ /* we want new depths every time */
+ glClear(GL_DEPTH_BUFFER_BIT);
+ }
+ }
+ }
+
+ ps->gl.is_init = true;
+ ps->gl.prev_id = id;
+
+ return true;
+}
+
+unsigned int gpu_select_pick_end(void)
+{
+ GPUPickState *ps = &g_pick_state;
+
+#ifdef DEBUG_PRINT
+ printf("%s\n", __func__);
+#endif
+
+ if (ps->is_cached == false) {
+ if (ps->gl.is_init) {
+ /* force finishing last pass */
+ gpu_select_pick_load_id(ps->gl.prev_id);
+ }
+
+ glPopAttrib();
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ /* assign but never free directly since it may be in cache */
+ DepthBufCache *rect_depth_final;
+
+ /* Store depth in cache */
+ if (ps->use_cache && !ps->is_cached) {
+ BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth);
+ ps->gl.rect_depth = NULL;
+ rect_depth_final = ps->cache.bufs.last;
+ }
+ else if (ps->is_cached) {
+ rect_depth_final = ps->cache.bufs.last;
+ }
+ else {
+ /* common case, no cache */
+ rect_depth_final = ps->gl.rect_depth;
+ }
+
+ unsigned int maxhits = g_pick_state.bufsize;
+ DepthID *depth_data;
+ unsigned int depth_data_len = 0;
+
+ if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ depth_data = ps->all.hits;
+ depth_data_len = ps->all.hits_len;
+ /* move ownership */
+ ps->all.hits = NULL;
+ ps->all.hits_len = 0;
+ ps->all.hits_len_alloc = 0;
+ }
+ else {
+ /* GPU_SELECT_PICK_NEAREST */
+
+ /* Over alloc (unlikely we have as many depths as pixels) */
+ unsigned int depth_data_len_first_pass = 0;
+ depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__);
+
+ /* Partially de-duplicating copy,
+ * when contiguous ID's are found - update their closest depth.
+ * This isn't essential but means there is less data to sort. */
+
+#define EVAL_TEST(i_src, i_dst) \
+ { \
+ const unsigned int id = ps->nearest.rect_id[i_dst]; \
+ if (id != SELECT_ID_NONE) { \
+ const depth_t depth = rect_depth_final->buf[i_src]; \
+ if (depth_last == NULL || depth_last->id != id) { \
+ DepthID *d = &depth_data[depth_data_len_first_pass++]; \
+ d->id = id; \
+ d->depth = depth; \
+ } \
+ else if (depth_last->depth > depth) { \
+ depth_last->depth = depth; \
+ } \
+ } \
+ } ((void)0)
+
+ {
+ DepthID *depth_last = NULL;
+ if (ps->is_cached == false) {
+ for (unsigned int i = 0; i < ps->src.rect_len; i++) {
+ EVAL_TEST(i, i);
+ }
+ }
+ else {
+ /* same as above but different rect sizes */
+ unsigned int i_src = ps->cache.sub_rect.start, i_dst = 0;
+ for (unsigned int j = 0; j < ps->cache.sub_rect.span_len; j++) {
+ const unsigned int i_src_end = i_src + ps->cache.sub_rect.span;
+ for (; i_src < i_src_end; i_src++, i_dst++) {
+ EVAL_TEST(i_src, i_dst);
+ }
+ i_src += ps->cache.sub_rect.skip;
+ }
+ }
+ }
+
+#undef EVAL_TEST
+
+ qsort(depth_data, depth_data_len_first_pass, sizeof(DepthID), depth_id_cmp);
+
+ /* Sort by ID's then keep the best depth for each ID */
+ depth_data_len = 0;
+ {
+ DepthID *depth_last = NULL;
+ for (unsigned int i = 0; i < depth_data_len_first_pass; i++) {
+ if (depth_last == NULL || depth_last->id != depth_data[i].id) {
+ depth_last = &depth_data[depth_data_len++];
+ *depth_last = depth_data[i];
+ }
+ else if (depth_last->depth > depth_data[i].depth) {
+ depth_last->depth = depth_data[i].depth;
+ }
+ }
+ }
+ }
+
+ /* Finally sort each unique (id, depth) pair by depth
+ * so the final hit-list is sorted by depth (nearest first) */
+ unsigned int hits = 0;
+
+ if (depth_data_len > maxhits) {
+ hits = (unsigned int)-1;
+ }
+ else {
+ /* leave sorting up to the caller */
+ qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
+
+ for (unsigned int i = 0; i < depth_data_len; i++) {
+#ifdef DEBUG_PRINT
+ printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
+#endif
+ /* first 3 are dummy values */
+ g_pick_state.buffer[hits][0] = 1;
+ g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */
+ g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
+ g_pick_state.buffer[hits][3] = depth_data[i].id;
+ hits++;
+ }
+ BLI_assert(hits < maxhits);
+ }
+
+ MEM_freeN(depth_data);
+
+ MEM_SAFE_FREE(ps->gl.rect_depth);
+ MEM_SAFE_FREE(ps->gl.rect_depth_test);
+
+ if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ /* 'hits' already freed as 'depth_data' */
+ }
+ else {
+ MEM_freeN(ps->nearest.rect_id);
+ ps->nearest.rect_id = NULL;
+ }
+
+ if (ps->use_cache) {
+ ps->is_cached = true;
+ }
+
+ return hits;
+}
+
+/* ----------------------------------------------------------------------------
+ * Caching
+ *
+ * Support multiple begin/end's reusing depth buffers.
+ */
+
+void gpu_select_pick_cache_begin(void)
+{
+ BLI_assert(g_pick_state.use_cache == false);
+#ifdef DEBUG_PRINT
+ printf("%s\n", __func__);
+#endif
+ g_pick_state.use_cache = true;
+ g_pick_state.is_cached = false;
+}
+
+void gpu_select_pick_cache_end(void)
+{
+#ifdef DEBUG_PRINT
+ printf("%s: with %d buffers\n", __func__, BLI_listbase_count(&g_pick_state.cache.bufs));
+#endif
+ g_pick_state.use_cache = false;
+ g_pick_state.is_cached = false;
+
+ BLI_freelistN(&g_pick_state.cache.bufs);
+}
+
+/* is drawing needed? */
+bool gpu_select_pick_is_cached(void)
+{
+ return g_pick_state.is_cached;
+}
+
+void gpu_select_pick_cache_load_id(void)
+{
+ BLI_assert(g_pick_state.is_cached == true);
+ GPUPickState *ps = &g_pick_state;
+#ifdef DEBUG_PRINT
+ printf("%s (building depth from cache)\n", __func__);
+#endif
+ for (DepthBufCache *rect_depth = ps->cache.bufs.first; rect_depth; rect_depth = rect_depth->next) {
+ if (rect_depth->next != NULL) {
+ /* we know the buffers differ, but this sub-region may not.
+ * double check before adding an id-pass */
+ if (g_pick_state.mode == GPU_SELECT_PICK_ALL) {
+ if (depth_buf_subrect_depth_any(rect_depth->next, &ps->cache.sub_rect)) {
+ gpu_select_load_id_pass_all(rect_depth->next);
+ }
+ }
+ else {
+ if (depth_buf_subrect_depth_any_filled(rect_depth, rect_depth->next, &ps->cache.sub_rect)) {
+ gpu_select_load_id_pass_nearest(rect_depth, rect_depth->next);
+ }
+ }
+ }
+ }
+}
diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h
new file mode 100644
index 00000000000..8935bd7b253
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_select_private.h
@@ -0,0 +1,53 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_select_private.h
+ * \ingroup gpu
+ *
+ * Selection implementations.
+ */
+
+#ifndef __GPU_SELECT_PRIVATE_H__
+#define __GPU_SELECT_PRIVATE_H__
+
+/* gpu_select_pick */
+void gpu_select_pick_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode);
+bool gpu_select_pick_load_id(unsigned int id);
+unsigned int gpu_select_pick_end(void);
+
+void gpu_select_pick_cache_begin(void);
+void gpu_select_pick_cache_end(void);
+bool gpu_select_pick_is_cached(void);
+void gpu_select_pick_cache_load_id(void);
+
+/* gpu_select_sample_query */
+void gpu_select_query_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode, int oldhits);
+bool gpu_select_query_load_id(unsigned int id);
+unsigned int gpu_select_query_end(void);
+
+
+#define SELECT_ID_NONE ((unsigned int)0xffffffff)
+
+#endif /* __GPU_SELECT_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c
new file mode 100644
index 00000000000..ba5fefc5227
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_select_sample_query.c
@@ -0,0 +1,209 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2014 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_select_sample_query.c
+ * \ingroup gpu
+ *
+ * Interface for accessing gpu-related methods for selection. The semantics will be
+ * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility.
+ */
+
+#include <stdlib.h>
+
+#include "GPU_select.h"
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_rect.h"
+
+#include "BLI_utildefines.h"
+
+#include "gpu_select_private.h"
+
+
+/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
+#define ALLOC_QUERIES 200
+
+typedef struct GPUQueryState {
+ /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */
+ bool query_issued;
+ /* array holding the OpenGL query identifiers */
+ unsigned int *queries;
+ /* array holding the id corresponding to each query */
+ unsigned int *id;
+ /* number of queries in *queries and *id */
+ unsigned int num_of_queries;
+ /* index to the next query to start */
+ unsigned int active_query;
+ /* cache on initialization */
+ unsigned int (*buffer)[4];
+ /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/
+ unsigned int bufsize;
+ /* mode of operation */
+ char mode;
+ unsigned int index;
+ int oldhits;
+} GPUQueryState;
+
+static GPUQueryState g_query_state = {0};
+
+
+void gpu_select_query_begin(
+ unsigned int (*buffer)[4], unsigned int bufsize,
+ const rcti *input, char mode,
+ int oldhits)
+{
+ float viewport[4];
+
+ g_query_state.query_issued = false;
+ g_query_state.active_query = 0;
+ g_query_state.num_of_queries = 0;
+ g_query_state.bufsize = bufsize;
+ g_query_state.buffer = buffer;
+ g_query_state.mode = mode;
+ g_query_state.index = 0;
+ g_query_state.oldhits = oldhits;
+
+ g_query_state.num_of_queries = ALLOC_QUERIES;
+
+ g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries");
+ g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids");
+ glGenQueries(g_query_state.num_of_queries, g_query_state.queries);
+
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
+ /* disable writing to the framebuffer */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* In order to save some fill rate we minimize the viewport using rect.
+ * We need to get the region of the scissor so that our geometry doesn't
+ * get rejected before the depth test. Should probably cull rect against
+ * scissor for viewport but this is a rare case I think */
+ glGetFloatv(GL_SCISSOR_BOX, viewport);
+ glViewport(viewport[0], viewport[1], BLI_rcti_size_x(input), BLI_rcti_size_y(input));
+
+ /* occlusion queries operates on fragments that pass tests and since we are interested on all
+ * objects in the view frustum independently of their order, we need to disable the depth test */
+ if (mode == GPU_SELECT_ALL) {
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ }
+ else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) {
+ glClear(GL_DEPTH_BUFFER_BIT);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ }
+ else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glDepthFunc(GL_EQUAL);
+ }
+}
+
+bool gpu_select_query_load_id(unsigned int id)
+{
+ if (g_query_state.query_issued) {
+ glEndQuery(GL_SAMPLES_PASSED);
+ }
+ /* if required, allocate extra queries */
+ if (g_query_state.active_query == g_query_state.num_of_queries) {
+ g_query_state.num_of_queries += ALLOC_QUERIES;
+ g_query_state.queries = MEM_reallocN(g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries));
+ g_query_state.id = MEM_reallocN(g_query_state.id, g_query_state.num_of_queries * sizeof(*g_query_state.id));
+ glGenQueries(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]);
+ }
+
+ glBeginQuery(GL_SAMPLES_PASSED, g_query_state.queries[g_query_state.active_query]);
+ g_query_state.id[g_query_state.active_query] = id;
+ g_query_state.active_query++;
+ g_query_state.query_issued = true;
+
+ if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS && g_query_state.index < g_query_state.oldhits) {
+ if (g_query_state.buffer[g_query_state.index][3] == id) {
+ g_query_state.index++;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+unsigned int gpu_select_query_end(void)
+{
+ int i;
+
+ unsigned int hits = 0;
+ const unsigned int maxhits = g_query_state.bufsize;
+
+ if (g_query_state.query_issued) {
+ glEndQuery(GL_SAMPLES_PASSED);
+ }
+
+ for (i = 0; i < g_query_state.active_query; i++) {
+ unsigned int result;
+ glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result);
+ if (result > 0) {
+ if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
+
+ if (hits < maxhits) {
+ g_query_state.buffer[hits][0] = 1;
+ g_query_state.buffer[hits][1] = 0xFFFF;
+ g_query_state.buffer[hits][2] = 0xFFFF;
+ g_query_state.buffer[hits][3] = g_query_state.id[i];
+
+ hits++;
+ }
+ else {
+ hits = -1;
+ break;
+ }
+ }
+ else {
+ int j;
+ /* search in buffer and make selected object first */
+ for (j = 0; j < g_query_state.oldhits; j++) {
+ if (g_query_state.buffer[j][3] == g_query_state.id[i]) {
+ g_query_state.buffer[j][1] = 0;
+ g_query_state.buffer[j][2] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries);
+ MEM_freeN(g_query_state.queries);
+ MEM_freeN(g_query_state.id);
+ glPopAttrib();
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ return hits;
+}
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 295182b3153..40653622d12 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -34,11 +34,11 @@
#include "BKE_global.h"
#include "GPU_compositing.h"
-#include "GPU_debug.h"
#include "GPU_extensions.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_texture.h"
+#include "GPU_matrix.h"
#include "gpu_shader_private.h"
@@ -50,7 +50,9 @@
extern char datatoc_gpu_shader_depth_only_frag_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_checker_frag_glsl[];
+extern char datatoc_gpu_shader_diag_stripes_frag_glsl[];
extern char datatoc_gpu_shader_simple_lighting_frag_glsl[];
+extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_frag_glsl[];
extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[];
extern char datatoc_gpu_shader_2D_vert_glsl[];
@@ -61,6 +63,7 @@ extern char datatoc_gpu_shader_2D_image_vert_glsl[];
extern char datatoc_gpu_shader_3D_image_vert_glsl[];
extern char datatoc_gpu_shader_image_color_frag_glsl[];
+extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
@@ -75,25 +78,34 @@ extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_vert_glsl[];
extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[];
+extern char datatoc_gpu_shader_instance_screen_aligned_axis_name_vert_glsl[];
+extern char datatoc_gpu_shader_instance_camera_vert_glsl[];
+extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
+extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
-extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[];
-extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[];
-extern char datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[];
+extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[];
extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[];
extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[];
-extern char datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl[];
-extern char datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[];
extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[];
-extern char datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl[];
-extern char datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl[];
-extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[];
+extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[];
+
+extern char datatoc_gpu_shader_2D_line_dashed_vert_glsl[];
+extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[];
extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[];
@@ -115,7 +127,7 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[];
extern char datatoc_gpu_shader_vsm_store_frag_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[];
extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[];
-extern char datatoc_gpu_shader_fx_vert_glsl[];
+extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
extern char datatoc_gpu_shader_fx_ssao_frag_glsl[];
extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
@@ -484,6 +496,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
}
#endif
+ shader->interface = ShaderInterface_create(shader->program);
+
return shader;
}
@@ -492,6 +506,7 @@ void GPU_shader_bind(GPUShader *shader)
BLI_assert(shader && shader->program);
glUseProgram(shader->program);
+ gpuBindMatrices(shader->program);
}
void GPU_shader_unbind(void)
@@ -515,6 +530,9 @@ void GPU_shader_free(GPUShader *shader)
if (shader->uniform_interface)
MEM_freeN(shader->uniform_interface);
+ if (shader->interface)
+ ShaderInterface_discard(shader->interface);
+
MEM_freeN(shader);
}
@@ -532,18 +550,23 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return glGetUniformBlockIndex(shader->program, name);
}
-void *GPU_shader_get_interface(GPUShader *shader)
+void *GPU_fx_shader_get_interface(GPUShader *shader)
{
return shader->uniform_interface;
}
+void *GPU_shader_get_interface(GPUShader *shader)
+{
+ return shader->interface;
+}
+
/* Clement : Temp */
int GPU_shader_get_program(GPUShader *shader)
{
return (int)shader->program;
}
-void GPU_shader_set_interface(GPUShader *shader, void *interface)
+void GPU_fx_shader_set_interface(GPUShader *shader, void *interface)
{
shader->uniform_interface = interface;
}
@@ -665,6 +688,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_edges_overlay_frag_glsl,
datatoc_gpu_shader_edges_overlay_geom_glsl },
[GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl },
+ [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl,
datatoc_gpu_shader_image_mask_uniform_color_frag_glsl },
@@ -679,6 +703,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_image_interlace_frag_glsl },
[GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl },
+ [GPU_SHADER_2D_DIAG_STRIPES] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_diag_stripes_frag_glsl },
+
[GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
@@ -686,6 +712,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
datatoc_gpu_shader_2D_smooth_color_frag_glsl },
[GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_color_frag_glsl },
+ [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
+ datatoc_gpu_shader_image_shuffle_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
@@ -700,23 +728,38 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl,
datatoc_gpu_shader_uniform_color_frag_glsl },
+ [GPU_SHADER_2D_LINE_DASHED_COLOR] = { datatoc_gpu_shader_2D_line_dashed_vert_glsl,
+ datatoc_gpu_shader_2D_line_dashed_frag_glsl },
+
+ [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] =
+ { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_simple_lighting_frag_glsl},
+ [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
[GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { datatoc_gpu_shader_instance_screen_aligned_axis_name_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+
+ [GPU_SHADER_CAMERA] = { datatoc_gpu_shader_instance_camera_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
+ [GPU_SHADER_DISTANCE_LINES] = { datatoc_gpu_shader_instance_distance_line_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl},
[GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
{ datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
[GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
{ datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl,
datatoc_gpu_shader_point_varying_color_frag_glsl },
- [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] =
- { datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl,
- datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl },
- [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] =
- { datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl,
- datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl },
- [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH] =
- { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl,
- datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
+ [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl },
[GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl,
datatoc_gpu_shader_point_uniform_color_frag_glsl },
[GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl,
@@ -726,23 +769,27 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] =
{ datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl,
datatoc_gpu_shader_point_varying_color_frag_glsl },
- [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] =
- { datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl,
- datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl },
- [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] =
- { datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl,
- datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_aa_frag_glsl },
+ [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] =
+ { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl,
+ datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
[GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
{ datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
+ [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl,
+ datatoc_gpu_shader_flat_color_frag_glsl,
+ datatoc_gpu_shader_instance_edges_variying_color_geom_glsl},
};
if (builtin_shaders[shader] == NULL) {
/* just a few special cases */
const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" :
- (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" : NULL;
+ (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" :
+ (shader == GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR) ? "#define USE_INSTANCE_COLOR;\n" : NULL;
const GPUShaderStages *stages = builtin_shader_stages + shader;
@@ -754,14 +801,6 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
stages = &legacy_fancy_edges;
}
- if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) {
- /* TODO: remove after switch to core profile (maybe) */
- static const GPUShaderStages legacy_fancy_edges =
- { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl,
- datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl };
- stages = &legacy_fancy_edges;
- }
-
/* common case */
builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom,
NULL, defines, 0, 0, 0);
@@ -792,7 +831,7 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
switch (effect) {
case GPU_SHADER_FX_SSAO:
- shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
break;
case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
@@ -837,7 +876,7 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp)
break;
case GPU_SHADER_FX_DEPTH_RESOLVE:
- shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+ shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
break;
}
diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h
index d5193e09aa4..10ffc17f0d5 100644
--- a/source/blender/gpu/intern/gpu_shader_private.h
+++ b/source/blender/gpu/intern/gpu_shader_private.h
@@ -25,6 +25,7 @@
#pragma once
#include "GPU_glew.h"
+#include "gawain/shader_interface.h"
struct GPUShader {
GLuint program; /* handle for full program (links shader stages below) */
@@ -33,8 +34,8 @@ struct GPUShader {
GLuint geometry; /* handle for geometry shader */
GLuint fragment; /* handle for fragment shader */
- int totattrib; /* total number of attributes */
- int uniforms; /* required uniforms */
-
void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */
+ /* NOTE: ^-- only FX compositing shaders use this */
+
+ ShaderInterface *interface; /* cached uniform & attrib interface for shader */
};
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 3513250993e..88dbe0c2ed9 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -62,19 +62,30 @@ struct GPUTexture {
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
bool depth; /* is a depth texture? */
+ bool stencil; /* is a stencil texture? */
};
-static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, bool *is_depth)
+static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil)
{
if (data_type == GPU_DEPTH_COMPONENT24 ||
data_type == GPU_DEPTH_COMPONENT16 ||
data_type == GPU_DEPTH_COMPONENT32F)
{
*is_depth = true;
+ *is_stencil = false;
+ *data_format = GL_FLOAT;
*format = GL_DEPTH_COMPONENT;
}
+ else if (data_type == GPU_DEPTH24_STENCIL8) {
+ *is_depth = true;
+ *is_stencil = true;
+ *data_format = GL_UNSIGNED_INT_24_8;
+ *format = GL_DEPTH_STENCIL;
+ }
else {
*is_depth = false;
+ *is_stencil = false;
+ *data_format = GL_FLOAT;
switch (components) {
case 1: *format = GL_RED; break;
@@ -93,9 +104,10 @@ static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type,
case GPU_RG32F: return GL_RG32F;
case GPU_RG16F: return GL_RG16F;
case GPU_RGBA8: return GL_RGBA8;
+ case GPU_R16F: return GL_R16F;
case GPU_R8: return GL_R8;
/* Special formats texture & renderbuffer */
- /* ** Add Format here **/
+ case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
/* Texture only format */
/* ** Add Format here **/
/* Special formats texture only */
@@ -148,20 +160,20 @@ static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int c
/* This tries to allocate video memory for a given texture
* If alloc fails, lower the resolution until it fits. */
static bool GPU_texture_try_alloc(
- GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, int channels,
- bool try_rescale, const float *fpixels, float **rescaled_fpixels)
+ GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, GLenum data_format,
+ int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels)
{
int r_width;
switch (proxy) {
case GL_PROXY_TEXTURE_1D:
- glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
break;
case GL_PROXY_TEXTURE_2D:
- glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
break;
case GL_PROXY_TEXTURE_3D:
- glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
break;
}
@@ -182,11 +194,11 @@ static bool GPU_texture_try_alloc(
if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break;
if (proxy == GL_PROXY_TEXTURE_1D)
- glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
else if (proxy == GL_PROXY_TEXTURE_2D)
- glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
else if (proxy == GL_PROXY_TEXTURE_3D)
- glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
}
@@ -213,7 +225,7 @@ static GPUTexture *GPU_texture_create_nD(
GPUTextureFormat data_type, int components, int samples,
const bool can_rescale, char err_out[256])
{
- GLenum format, internalformat, proxy;
+ GLenum format, internalformat, proxy, data_format;
float *rescaled_fpixels = NULL;
const float *pix;
bool valid;
@@ -228,6 +240,7 @@ static GPUTexture *GPU_texture_create_nD(
tex->d = d;
tex->number = -1;
tex->refcount = 1;
+ tex->fb_attachment = -1;
if (n == 1) {
if (h == 0)
@@ -245,12 +258,10 @@ static GPUTexture *GPU_texture_create_nD(
tex->target_base = tex->target = GL_TEXTURE_3D;
}
- tex->fb_attachment = -1;
-
if (samples && n == 2 && d == 0)
tex->target = GL_TEXTURE_2D_MULTISAMPLE;
- internalformat = GPU_texture_get_format(components, data_type, &format, &tex->depth);
+ internalformat = GPU_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil);
/* Generate Texture object */
glGenTextures(1, &tex->bindcode);
@@ -278,7 +289,7 @@ static GPUTexture *GPU_texture_create_nD(
proxy = GL_PROXY_TEXTURE_1D;
}
- valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, components, can_rescale, fpixels,
+ valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels,
&rescaled_fpixels);
if (!valid) {
@@ -294,7 +305,7 @@ static GPUTexture *GPU_texture_create_nD(
pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, GL_FLOAT, pix);
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, data_format, pix);
}
else if (tex->target == GL_TEXTURE_1D_ARRAY ||
tex->target == GL_TEXTURE_2D ||
@@ -303,14 +314,14 @@ static GPUTexture *GPU_texture_create_nD(
if (samples) {
glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
if (pix)
- glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, GL_FLOAT, pix);
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pix);
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, pix);
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, data_format, pix);
}
}
else {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, pix);
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, pix);
}
if (rescaled_fpixels)
@@ -494,6 +505,11 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, err_out);
}
+GPUTexture *GPU_texture_create_depth_with_stencil(int w, int h, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH24_STENCIL8, 1, 0, false, err_out);
+}
+
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
{
return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, samples, false, err_out);
@@ -708,11 +724,16 @@ int GPU_texture_height(const GPUTexture *tex)
return tex->h;
}
-int GPU_texture_depth(const GPUTexture *tex)
+bool GPU_texture_depth(const GPUTexture *tex)
{
return tex->depth;
}
+bool GPU_texture_stencil(const GPUTexture *tex)
+{
+ return tex->stencil;
+}
+
int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
return tex->bindcode;
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 62ba06b7a0a..7c2cb8cd4bb 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -33,11 +33,14 @@
#include <string.h>
+#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "DNA_vec_types.h"
+#include "BKE_global.h"
+
#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_immediate.h"
@@ -55,98 +58,172 @@ struct GPUViewport {
GPUTexture *debug_depth;
int size[2];
- /* Viewport Buffer Storage */
- /* TODO indentify to what engine conf are theses buffers */
- DefaultFramebufferList *fbl;
- DefaultTextureList *txl;
- DefaultPassList *psl;
- StorageList *stl;
+ ListBase data; /* ViewportEngineData wrapped in LinkData */
+ unsigned int data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */
- char engine_name[32];
+ FramebufferList *fbl;
+ TextureList *txl;
};
-static void GPU_viewport_buffers_free(GPUViewport *viewport);
-static void GPU_viewport_passes_free(GPUViewport *viewport);
-static void GPU_viewport_storage_free(GPUViewport *viewport);
+static void GPU_viewport_buffers_free(FramebufferList *fbl, TextureList *txl);
+static void GPU_viewport_storage_free(StorageList *stl);
+static void GPU_viewport_passes_free(PassList *psl);
GPUViewport *GPU_viewport_create(void)
{
GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList");
viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList");
- viewport->psl = MEM_callocN(sizeof(PassList), "PassList");
- viewport->stl = MEM_callocN(sizeof(StorageList), "StorageList");
viewport->size[0] = viewport->size[1] = -1;
return viewport;
}
-void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str)
+void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
{
- *fbs = viewport->fbl;
- *txs = viewport->txl;
- *pss = viewport->psl;
- *str = viewport->stl;
+ LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData");
+ ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
+ data->engine_type = engine_type;
+
+ data->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList");
+ data->txl = MEM_callocN(sizeof(TextureList), "TextureList");
+ data->psl = MEM_callocN(sizeof(PassList), "PassList");
+ data->stl = MEM_callocN(sizeof(StorageList), "StorageList");
+
+ ld->data = data;
+ BLI_addtail(&viewport->data, ld);
+
+ return data;
}
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine)
+static void GPU_viewport_engines_data_free(GPUViewport *viewport)
{
- /* add one pixel because of scissor test */
- int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1;
+ LinkData *next;
+ for (LinkData *link = viewport->data.first; link; link = next) {
+ next = link->next;
+ ViewportEngineData *data = link->data;
-#ifndef WITH_VIEWPORT_CACHE_TEST
- /* TODO for testing only, we need proper cache invalidation */
- GPU_viewport_passes_free(viewport);
-#endif
+ GPU_viewport_buffers_free(data->fbl, data->txl);
+ GPU_viewport_passes_free(data->psl);
+ GPU_viewport_storage_free(data->stl);
+
+ MEM_freeN(data->fbl);
+ MEM_freeN(data->txl);
+ MEM_freeN(data->psl);
+ MEM_freeN(data->stl);
+
+ MEM_freeN(data);
+
+ BLI_remlink(&viewport->data, link);
+ MEM_freeN(link);
+ }
+}
+
+void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type)
+{
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *vdata = link->data;
+ if (vdata->engine_type == engine_type) {
+ return vdata;
+ }
+ }
+ return NULL;
+}
+
+void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
+{
+ return viewport->fbl;
+}
- if (!STREQ(engine, viewport->engine_name)) {
- GPU_viewport_storage_free(viewport);
- GPU_viewport_buffers_free(viewport);
+void *GPU_viewport_texture_list_get(GPUViewport *viewport)
+{
+ return viewport->txl;
+}
+
+void GPU_viewport_size_get(GPUViewport *viewport, int *size)
+{
+ size[0] = viewport->size[0];
+ size[1] = viewport->size[1];
+}
+
+bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash)
+{
+ bool dirty = false;
+
+ /* TODO for testing only, we need proper cache invalidation */
+ if (G.debug_value != 666 && G.debug_value != 667) {
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ GPU_viewport_passes_free(data->psl);
+ }
+ dirty = true;
+ }
- BLI_strncpy(viewport->engine_name, engine, 32);
+ if (viewport->data_hash != hash) {
+ GPU_viewport_engines_data_free(viewport);
+ dirty = true;
}
- if (viewport->fbl->default_fb) {
+ viewport->data_hash = hash;
+
+ return dirty;
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+ DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl;
+ DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl;
+
+ /* add one pixel because of scissor test */
+ int rect_w = BLI_rcti_size_x(rect) + 1;
+ int rect_h = BLI_rcti_size_y(rect) + 1;
+
+ if (dfbl->default_fb) {
if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) {
- GPU_viewport_buffers_free(viewport);
+ GPU_viewport_buffers_free(viewport->fbl, viewport->txl);
+
+ for (LinkData *link = viewport->data.first; link; link = link->next) {
+ ViewportEngineData *data = link->data;
+ GPU_viewport_buffers_free(data->fbl, data->txl);
+ }
}
}
- if (!viewport->fbl->default_fb) {
+ if (!dfbl->default_fb) {
bool ok = true;
viewport->size[0] = rect_w;
viewport->size[1] = rect_h;
- viewport->fbl->default_fb = GPU_framebuffer_create();
- if (!viewport->fbl->default_fb) {
+ dfbl->default_fb = GPU_framebuffer_create();
+ if (!dfbl->default_fb) {
ok = false;
goto cleanup;
}
/* Color */
/* No multi samples for now */
- viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
- if (!viewport->txl->color) {
+ dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
+ if (!dtxl->color) {
ok = false;
goto cleanup;
}
- if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) {
+ if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0)) {
ok = false;
goto cleanup;
}
/* Depth */
- viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL);
- if (!viewport->txl->depth) {
+ dtxl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL);
+ if (!dtxl->depth) {
ok = false;
goto cleanup;
}
- else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) {
+ else if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0)) {
ok = false;
goto cleanup;
}
- else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) {
+ else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) {
ok = false;
goto cleanup;
}
@@ -161,12 +238,14 @@ cleanup:
GPU_framebuffer_restore();
}
- GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0);
+ GPU_framebuffer_slots_bind(dfbl->default_fb, 0);
}
static void draw_ofs_to_screen(GPUViewport *viewport)
{
- GPUTexture *color = viewport->txl->color;
+ DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl;
+
+ GPUTexture *color = dtxl->color;
const float w = (float)GPU_texture_width(color);
const float h = (float)GPU_texture_height(color);
@@ -176,12 +255,11 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
-
GPU_texture_bind(color, 0);
immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- immBegin(GL_QUADS, 4);
+ immBegin(GL_TRIANGLE_STRIP, 4);
immAttrib2f(texcoord, 0.0f, 0.0f);
immVertex2f(pos, 0.0f, 0.0f);
@@ -189,12 +267,12 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
immAttrib2f(texcoord, 1.0f, 0.0f);
immVertex2f(pos, w, 0.0f);
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
-
immAttrib2f(texcoord, 0.0f, 1.0f);
immVertex2f(pos, 0.0f, h);
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
immEnd();
GPU_texture_unbind(color);
@@ -204,21 +282,22 @@ static void draw_ofs_to_screen(GPUViewport *viewport)
void GPU_viewport_unbind(GPUViewport *viewport)
{
- if (viewport->fbl->default_fb) {
+ DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl;
+
+ if (dfbl->default_fb) {
GPU_framebuffer_texture_unbind(NULL, NULL);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
/* This might be bandwidth limiting */
draw_ofs_to_screen(viewport);
}
}
-static void GPU_viewport_buffers_free(GPUViewport *viewport)
+static void GPU_viewport_buffers_free(FramebufferList *fbl, TextureList *txl)
{
- FramebufferList *fbl = (FramebufferList *)viewport->fbl;
- TextureList *txl = (TextureList *)viewport->txl;
int i;
for (i = MAX_BUFFERS - 1; i > -1; --i) {
GPUFrameBuffer *fb = fbl->framebuffers[i];
@@ -236,10 +315,8 @@ static void GPU_viewport_buffers_free(GPUViewport *viewport)
}
}
-static void GPU_viewport_storage_free(GPUViewport *viewport)
+static void GPU_viewport_storage_free(StorageList *stl)
{
- StorageList *stl = (StorageList *)viewport->stl;
-
for (int i = MAX_STORAGE - 1; i > -1; --i) {
void *storage = stl->storage[i];
if (storage) {
@@ -249,12 +326,9 @@ static void GPU_viewport_storage_free(GPUViewport *viewport)
}
}
-static void GPU_viewport_passes_free(GPUViewport *viewport)
+static void GPU_viewport_passes_free(PassList *psl)
{
- PassList *psl = (PassList *)viewport->psl;
- int i;
-
- for (i = MAX_PASSES - 1; i > -1; --i) {
+ for (int i = MAX_PASSES - 1; i > -1; --i) {
struct DRWPass *pass = psl->passes[i];
if (pass) {
DRW_pass_free(pass);
@@ -266,15 +340,13 @@ static void GPU_viewport_passes_free(GPUViewport *viewport)
void GPU_viewport_free(GPUViewport *viewport)
{
- GPU_viewport_debug_depth_free(viewport);
- GPU_viewport_buffers_free(viewport);
- GPU_viewport_passes_free(viewport);
- GPU_viewport_storage_free(viewport);
+ GPU_viewport_engines_data_free(viewport);
+ GPU_viewport_buffers_free(viewport->fbl, viewport->txl);
MEM_freeN(viewport->fbl);
MEM_freeN(viewport->txl);
- MEM_freeN(viewport->psl);
- MEM_freeN(viewport->stl);
+
+ GPU_viewport_debug_depth_free(viewport);
}
/****************** debug ********************/
@@ -320,7 +392,7 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con
immUniform1f("zfar", zfar);
immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
- immBegin(GL_QUADS, 4);
+ immBegin(GL_TRIANGLE_STRIP, 4);
immAttrib2f(texcoord, 0.0f, 0.0f);
immVertex2f(pos, 0.0f, 0.0f);
@@ -328,12 +400,12 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con
immAttrib2f(texcoord, 1.0f, 0.0f);
immVertex2f(pos, w, 0.0f);
- immAttrib2f(texcoord, 1.0f, 1.0f);
- immVertex2f(pos, w, h);
-
immAttrib2f(texcoord, 0.0f, 1.0f);
immVertex2f(pos, 0.0f, h);
+ immAttrib2f(texcoord, 1.0f, 1.0f);
+ immVertex2f(pos, w, h);
+
immEnd();
GPU_texture_unbind(viewport->debug_depth);
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
index a6c00b080b2..f5217a9d238 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl
@@ -1,6 +1,7 @@
uniform mat4 ModelViewProjectionMatrix;
+/* Keep in sync with intern/opencolorio/gpu_shader_display_transform_vertex.glsl */
#if __VERSION__ == 120
attribute vec2 texCoord;
attribute vec2 pos;
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
new file mode 100644
index 00000000000..85aab7e06ef
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl
@@ -0,0 +1,25 @@
+
+// Draw dashed lines, perforated in screen space.
+// Based on a (3D) version by Mike Erwin.
+
+#if __VERSION__ == 120
+ noperspective varying float distance_along_line;
+ #define fragColor gl_FragColor
+#else
+ noperspective in float distance_along_line;
+ out vec4 fragColor;
+#endif
+
+uniform float dash_width;
+uniform float dash_width_on;
+uniform vec4 color1;
+uniform vec4 color2;
+
+void main()
+{
+ if (mod(distance_along_line, dash_width) <= dash_width_on) {
+ fragColor = color1;
+ } else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl
new file mode 100644
index 00000000000..7b4207142e6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl
@@ -0,0 +1,22 @@
+
+// Draw dashed lines, perforated in screen space.
+// Based on a (3D) version by Mike Erwin.
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 line_origin; // = pos for one vertex of the line
+ noperspective varying float distance_along_line;
+#else
+ in vec2 pos;
+ in vec2 line_origin;
+ noperspective out float distance_along_line;
+#endif
+
+void main()
+{
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+
+ distance_along_line = distance(line_origin, pos);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
index 201e5e90ecc..201e5e90ecc 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
index a37ae16f837..a37ae16f837 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
index d3a142cc7bd..d3a142cc7bd 100644
--- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
index 287f95b48ab..287f95b48ab 100644
--- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
index d05920002ed..d05920002ed 100644
--- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
index a0141f1ab2c..5f7455582cd 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl
@@ -21,6 +21,10 @@
#define STIPPLE_DIAG_STRIPES 4
#define STIPPLE_DIAG_STRIPES_SWAP 5
+#ifndef NO_SPECULAR
+uniform mat4 ProjectionMatrix;
+#endif
+
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
varying vec3 eyespace_vert_pos;
@@ -163,7 +167,7 @@ void main()
#ifndef NO_SPECULAR
/* view vector computation, depends on orthographics or perspective */
- vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
+ vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0);
#endif
for (int i = 0; i < NUM_SCENE_LIGHTS; i++) {
diff --git a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
index 42fbdadf1d1..dbf6c267f14 100644
--- a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl
@@ -1,4 +1,8 @@
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if defined(USE_FLAT_NORMAL)
varying vec3 eyespace_vert_pos;
@@ -29,15 +33,15 @@ varying float gl_ClipDistance[6];
void main()
{
- vec4 co = gl_ModelViewMatrix * gl_Vertex;
+ vec4 co = ModelViewMatrix * gl_Vertex;
#if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING)
#if !defined(USE_FLAT_NORMAL)
- varying_normal = normalize(gl_NormalMatrix * gl_Normal);
+ varying_normal = normalize(NormalMatrix * gl_Normal);
#endif
#if defined(USE_FLAT_NORMAL)
/* transform vertex into eyespace */
- eyespace_vert_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
+ eyespace_vert_pos = (ModelViewMatrix * gl_Vertex).xyz;
#endif
#ifndef USE_SOLID_LIGHTING
@@ -45,7 +49,7 @@ void main()
#endif
#endif
- gl_Position = gl_ProjectionMatrix * co;
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
diff --git a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
new file mode 100644
index 00000000000..74cf1c5a3dc
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl
@@ -0,0 +1,24 @@
+
+uniform vec4 color1;
+uniform vec4 color2;
+uniform int size1;
+uniform int size2;
+
+#if __VERSION__ == 120
+ #define fragColor gl_FragColor
+#else
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2));
+
+ if (phase < size1)
+ {
+ fragColor = color1;
+ }
+ else {
+ fragColor = color2;
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
index 71a43d1b7ae..fb1d0aafe05 100644
--- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl
@@ -1,5 +1,5 @@
-//mat4 ModelViewProjectionMatrix;
+uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
in float edgeWidthModulator;
@@ -8,6 +8,6 @@ out vec4 pos_xformed;
out float widthModulator;
void main() {
- pos_xformed = gl_ModelViewProjectionMatrix * vec4(pos, 1.0);
+ pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0);
widthModulator = edgeWidthModulator;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
index 3819203bcd9..45f86e036a1 100644
--- a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl
@@ -1,5 +1,13 @@
-varying vec3 coords;
+#if __VERSION__ == 120
+ varying vec3 coords;
+ #define fragColor gl_FragColor
+#else
+ in vec3 coords;
+ out vec4 fragColor;
+ #define texture1D texture
+ #define texture3D texture
+#endif
uniform sampler3D flame_texture;
uniform sampler1D spectrum_texture;
@@ -13,5 +21,5 @@ void main()
color.rgb = emission.a * emission.rgb;
color.a = emission.a;
- gl_FragColor = color;
+ fragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
new file mode 100644
index 00000000000..cf2d28343cc
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl
@@ -0,0 +1,16 @@
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 uvs;
+ varying vec4 uvcoordsvar;
+#else
+ in vec2 pos;
+ in vec2 uvs;
+ out vec4 uvcoordsvar;
+#endif
+
+void main()
+{
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
index e04cd7d3306..3ba455d34e7 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
@@ -1,5 +1,10 @@
uniform sampler2D depthbuffer;
-varying vec4 uvcoordsvar;
+
+#if __VERSION__ == 120
+ varying vec4 uvcoordsvar;
+#else
+ in vec4 uvcoordsvar;
+#endif
void main(void)
{
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
index 338ef6d51a7..6b3f1b99594 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -16,17 +16,35 @@ uniform vec4 dof_params;
// viewvectors for reconstruction of world space
uniform vec4 viewvecs[3];
-// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
-
-/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
-
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+#if __VERSION__ == 120
+ // coordinates on framebuffer in normalized (0.0-1.0) uv space
+ varying vec4 uvcoordsvar;
+
+ /* color texture coordinates, offset by a small amount */
+ varying vec2 color_uv1;
+ varying vec2 color_uv2;
+
+ varying vec2 depth_uv1;
+ varying vec2 depth_uv2;
+ varying vec2 depth_uv3;
+ varying vec2 depth_uv4;
+
+ #define FragColor gl_FragColor
+#else
+ // coordinates on framebuffer in normalized (0.0-1.0) uv space
+ in vec4 uvcoordsvar;
+
+ /* color texture coordinates, offset by a small amount */
+ in vec2 color_uv1;
+ in vec2 color_uv2;
+
+ in vec2 depth_uv1;
+ in vec2 depth_uv2;
+ in vec2 depth_uv3;
+ in vec2 depth_uv4;
+
+ out vec4 FragColor;
+#endif
float calculate_far_coc(in float zdepth)
@@ -102,7 +120,7 @@ void first_pass()
coc = max(calculate_near_coc(zdepth), coc);
final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w));
- gl_FragColor = vec4(color.rgb, final_coc);
+ FragColor = vec4(color.rgb, final_coc);
}
/* second pass, gaussian blur the downsampled image */
@@ -119,7 +137,7 @@ void second_pass()
color += texture2D(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375;
color += texture2D(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625;
- gl_FragColor = color;
+ FragColor = color;
}
@@ -129,7 +147,7 @@ void third_pass()
vec4 color = texture2D(colorbuffer, uvcoordsvar.xy);
vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
float coc = 2.0 * max(color_blurred.a, color.a); -color.a;
- gl_FragColor = vec4(color.rgb, coc);
+ FragColor = vec4(color.rgb, coc);
}
@@ -141,7 +159,7 @@ void fourth_pass()
color += texture2D(colorbuffer, uvcoordsvar.xw);
color += texture2D(colorbuffer, uvcoordsvar.yw);
- gl_FragColor = color / 4.0;
+ FragColor = color / 4.0;
}
vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
@@ -188,7 +206,7 @@ void fifth_pass()
color /= dot(factors, vec4(1.0));
/* using original color is not correct, but use that for now because alpha of
* blurred buffers uses CoC instead */
- gl_FragColor = vec4(color.rgb, color_orig.a);
+ FragColor = vec4(color.rgb, color_orig.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
index 182113367d3..46feb91de6e 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -20,18 +20,42 @@ uniform vec4 dof_params;
/* viewvectors for reconstruction of world space */
uniform vec4 viewvecs[3];
-/* initial uv coordinate */
-varying vec2 uvcoord;
-
-/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
-varying vec4 color;
+#if __VERSION__ == 120
+ /* initial uv coordinate */
+ varying vec2 uvcoord;
+
+ /* coordinate used for calculating radius et al set in geometry shader */
+ varying vec2 particlecoord;
+ varying vec4 color;
+
+ /* downsampling coordinates */
+ varying vec2 downsample1;
+ varying vec2 downsample2;
+ varying vec2 downsample3;
+ varying vec2 downsample4;
+
+ #define fragData0 gl_FragData[0]
+ #define fragData1 gl_FragData[1]
+ #define fragData2 gl_FragData[2]
+#else
+ /* initial uv coordinate */
+ in vec2 uvcoord;
+
+ /* coordinate used for calculating radius et al set in geometry shader */
+ in vec2 particlecoord;
+ flat in vec4 color;
+
+ /* downsampling coordinates */
+ in vec2 downsample1;
+ in vec2 downsample2;
+ in vec2 downsample3;
+ in vec2 downsample4;
+
+ layout(location = 0) out vec4 fragData0;
+ layout(location = 1) out vec4 fragData1;
+ layout(location = 2) out vec4 fragData2;
+#endif
-/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
#define M_PI 3.1415926535897932384626433832795
@@ -82,16 +106,16 @@ void downsample_pass()
float norm_far = dot(far_weights, vec4(1.0));
/* now write output to weighted buffers. */
- gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
+ fragData0 = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z +
color4 * near_weights.w;
- gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
+ fragData1 = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z +
color4 * far_weights.w;
if (norm_near > 0.0)
- gl_FragData[0] /= norm_near;
+ fragData0 /= norm_near;
if (norm_far > 0.0)
- gl_FragData[1] /= norm_far;
- gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0);
+ fragData1 /= norm_far;
+ fragData2 = vec4(near_coc, far_coc, 0.0, 1.0);
}
/* accumulate color in the near/far blur buffers */
@@ -102,16 +126,16 @@ void accumulate_pass(void) {
if (dof_params.w == 0.0)
r = 1.0;
else
- r = cos(M_PI / dof_params.w) /
- (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
+ r = cos(M_PI / dof_params.w) /
+ (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI))));
if (dot(particlecoord, particlecoord) > r * r)
discard;
- gl_FragData[0] = color;
+ fragData0 = color;
}
-#define MERGE_THRESHOLD 4.0
+#define MERGE_THRESHOLD 4.0
/* combine the passes, */
void final_pass(void) {
vec4 finalcolor;
@@ -152,7 +176,9 @@ void final_pass(void) {
finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight);
}
- gl_FragData[0] = finalcolor;
+ fragData0 = finalcolor;
+ // fragData0 = vec4(nearweight, farweight, 0.0, 1.0);
+ // fragData0 = vec4(nearcolor.rgb, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
index 4c650e7695f..c9a726a007e 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
@@ -24,7 +24,7 @@ uniform sampler2D cocbuffer;
#else
in vec2 uvcoord[];
out vec2 particlecoord;
- out vec4 color;
+ flat out vec4 color;
#endif
#define M_PI 3.1415926535897932384626433832795
@@ -46,21 +46,23 @@ void main()
vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y);
- gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
color = colortex;
+
+ gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, -1.0);
EmitVertex();
+
gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(-1.0, 1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, -1.0);
- color = colortex;
EmitVertex();
+
gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
particlecoord = vec2(1.0, 1.0);
- color = colortex;
EmitVertex();
+
EndPrimitive();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
index 09a0c75facc..78fe0e563f2 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
@@ -1,27 +1,47 @@
-uniform vec2 invrendertargetdim;
-uniform ivec2 rendertargetdim;
-/* initial uv coordinate */
-varying vec2 uvcoord;
-/* coordinate used for calculating radius et al set in geometry shader */
-varying vec2 particlecoord;
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 uvs;
+ /* initial uv coordinate */
+ varying vec2 uvcoord;
+
+ /* coordinate used for calculating radius et al set in geometry shader */
+ varying vec2 particlecoord;
+
+ /* downsampling coordinates */
+ varying vec2 downsample1;
+ varying vec2 downsample2;
+ varying vec2 downsample3;
+ varying vec2 downsample4;
+#else
+ in vec2 pos;
+ in vec2 uvs;
+ /* initial uv coordinate */
+ out vec2 uvcoord;
+
+ /* coordinate used for calculating radius et al set in geometry shader */
+ out vec2 particlecoord;
+
+ /* downsampling coordinates */
+ out vec2 downsample1;
+ out vec2 downsample2;
+ out vec2 downsample3;
+ out vec2 downsample4;
+#endif
-/* downsampling coordinates */
-varying vec2 downsample1;
-varying vec2 downsample2;
-varying vec2 downsample3;
-varying vec2 downsample4;
+uniform vec2 invrendertargetdim;
+uniform ivec2 rendertargetdim;
void vert_dof_downsample()
{
/* gather pixels from neighbors. half dimensions means we offset half a pixel to
* get this right though it's possible we may lose a pixel at some point */
- downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim;
- downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim;
- downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim;
- downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim;
+ downsample1 = uvs.xy + vec2(-0.5, -0.5) * invrendertargetdim;
+ downsample2 = uvs.xy + vec2(-0.5, 0.5) * invrendertargetdim;
+ downsample3 = uvs.xy + vec2(0.5, 0.5) * invrendertargetdim;
+ downsample4 = uvs.xy + vec2(0.5, -0.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
/* geometry shading pass, calculate a texture coordinate based on the indexed id */
@@ -42,8 +62,8 @@ void vert_dof_coc_scatter_pass()
void vert_dof_final()
{
- uvcoord = gl_MultiTexCoord0.xy;
- gl_Position = gl_Vertex;
+ uvcoord = uvs;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
index 63b57d5775c..eb2b6b04da8 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -1,51 +1,72 @@
uniform vec2 invrendertargetdim;
-//texture coordinates for framebuffer read
-varying vec4 uvcoordsvar;
-/* color texture coordinates, offset by a small amount */
-varying vec2 color_uv1;
-varying vec2 color_uv2;
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 uvs;
-varying vec2 depth_uv1;
-varying vec2 depth_uv2;
-varying vec2 depth_uv3;
-varying vec2 depth_uv4;
+ //texture coordinates for framebuffer read
+ varying vec4 uvcoordsvar;
+
+ /* color texture coordinates, offset by a small amount */
+ varying vec2 color_uv1;
+ varying vec2 color_uv2;
+
+ varying vec2 depth_uv1;
+ varying vec2 depth_uv2;
+ varying vec2 depth_uv3;
+ varying vec2 depth_uv4;
+#else
+ in vec2 pos;
+ in vec2 uvs;
+
+ //texture coordinates for framebuffer read
+ out vec4 uvcoordsvar;
+
+ /* color texture coordinates, offset by a small amount */
+ out vec2 color_uv1;
+ out vec2 color_uv2;
+
+ out vec2 depth_uv1;
+ out vec2 depth_uv2;
+ out vec2 depth_uv3;
+ out vec2 depth_uv4;
+#endif
//very simple shader for gull screen FX, just pass values on
void vert_generic()
{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_first_pass()
{
/* we offset the texture coordinates by 1.5 pixel,
* then we reuse that to sample the surrounding pixels */
- color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ color_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ color_uv2 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim;
- depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim;
- depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim;
- depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim;
+ depth_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim;
+ depth_uv2 = uvs.xy + vec2(-0.5, -1.5) * invrendertargetdim;
+ depth_uv3 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim;
+ depth_uv4 = uvs.xy + vec2(1.5, -1.5) * invrendertargetdim;
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fourth_pass()
{
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
- uvcoordsvar = gl_MultiTexCoord0.xxyy +
+ uvcoordsvar = uvs.xxyy +
halfpixel *
vec4(invrendertargetdim.x,
invrendertargetdim.x,
invrendertargetdim.y,
invrendertargetdim.y);
- gl_Position = gl_Vertex;
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void vert_dof_fifth_pass()
@@ -53,8 +74,8 @@ void vert_dof_fifth_pass()
vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
color_uv1 = vec2(0.5, 1.5) * invrendertargetdim;
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
+ uvcoordsvar = vec4(uvs, 0.0, 0.0);
+ gl_Position = vec4(pos, 0.0, 1.0);
}
void main()
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
index 1dc49b52be1..7aa6786d292 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
@@ -1,14 +1,17 @@
+uniform mat4 ProjectionMatrix;
+
/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
* we change the factors from the article to fit the OpennGL model. */
#ifdef PERSP_MATRIX
+
/* perspective camera code */
vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
{
float d = 2.0 * depth - 1.0;
- float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]);
+ float zview = -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]);
return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
}
@@ -18,7 +21,7 @@ vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
vec4 d = 2.0 * depth - vec4(1.0);
/* return positive value, so sign differs! */
- return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2]));
+ return vec4(ProjectionMatrix[3][2]) / (d + vec4(ProjectionMatrix[2][2]));
}
#else
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
index 50c8e255162..4a6cc09f5ea 100644
--- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -1,3 +1,4 @@
+
// color buffer
uniform sampler2D colorbuffer;
@@ -9,8 +10,15 @@ uniform sampler1D ssao_concentric_tex;
// depth buffer
uniform sampler2D depthbuffer;
-// coordinates on framebuffer in normalized (0.0-1.0) uv space
-varying vec4 uvcoordsvar;
+
+#if __VERSION__ == 120
+ // coordinates on framebuffer in normalized (0.0-1.0) uv space
+ varying vec4 uvcoordsvar;
+ #define FragColor gl_FragColor
+#else
+ in vec4 uvcoordsvar;
+ out vec4 FragColor;
+#endif
/* ssao_params.x : pixel scale for the ssao radious */
/* ssao_params.y : factor for the ssao darkening */
@@ -46,9 +54,9 @@ float calculate_ssao_factor(float depth)
/* find the offset in screen space by multiplying a point
* in camera space at the depth of the point by the projection matrix. */
vec2 offset;
- float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3];
- offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord;
- offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord;
+ float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
+ offset.x = ProjectionMatrix[0][0] * ssao_params.x / homcoord;
+ offset.y = ProjectionMatrix[1][1] * ssao_params.x / homcoord;
/* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
offset *= 0.5;
@@ -90,5 +98,5 @@ void main()
float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy);
vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth));
- gl_FragColor = vec4(final_color.rgb, scene_col.a);
+ FragColor = vec4(final_color.rgb, scene_col.a);
}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
deleted file mode 100644
index 5194e414520..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-varying vec4 uvcoordsvar;
-
-//very simple shader for full screen FX, just pass values on
-
-void main()
-{
- uvcoordsvar = gl_MultiTexCoord0;
- gl_Position = gl_Vertex;
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
index fe630dbeddb..545910d39ca 100644
--- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -1,3 +1,6 @@
+
+uniform mat4 ProjectionMatrix;
+
uniform int PrimitiveIdBase;
uniform int osd_active_uv_offset;
@@ -69,7 +72,7 @@ void emit_flat(int index, vec3 normal)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
@@ -90,7 +93,7 @@ void emit_smooth(int index)
set_mtface_vertex_attrs(st);
- gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ gl_Position = ProjectionMatrix * inpt[index].v.position;
EmitVertex();
}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
new file mode 100644
index 00000000000..fa4f41b79fb
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl
@@ -0,0 +1,22 @@
+
+#if __VERSION__ == 120
+ varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2D texture
+#endif
+
+uniform sampler2D image;
+uniform vec4 color;
+uniform vec4 shuffle;
+
+void main()
+{
+ vec4 sample = texture2D(image, texCoord_interp);
+ fragColor = vec4(sample.r * shuffle.r +
+ sample.g * shuffle.g +
+ sample.b * shuffle.b +
+ sample.a * shuffle.a) * color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
new file mode 100644
index 00000000000..aec8fd9b0a1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl
@@ -0,0 +1,50 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in float pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in vec4 corners[2]; /* trouble fetching vec2 */
+in float depth;
+in vec4 tria;
+in mat4 InstanceModelMatrix;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 pPos;
+
+ if (pos == 1.0) {
+ pPos = vec3(corners[0].xy, depth);
+ }
+ else if (pos == 2.0) {
+ pPos = vec3(corners[0].zw, depth);
+ }
+ else if (pos == 3.0) {
+ pPos = vec3(corners[1].xy, depth);
+ }
+ else if (pos == 4.0) {
+ pPos = vec3(corners[1].zw, depth);
+ }
+ else if (pos == 5.0) {
+ pPos = vec3(tria.xy, depth);
+ }
+ else if (pos == 6.0) {
+ vec2 ofs = tria.xy - corners[0].xy;
+ ofs.x = -ofs.x;
+ pPos = vec3(corners[1].zw + ofs, depth);
+ }
+ else if (pos == 7.0) {
+ pPos = vec3(tria.zw, depth);
+ }
+ else {
+ pPos = vec3(0.0);
+ }
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0);
+
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
new file mode 100644
index 00000000000..142df70e68a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl
@@ -0,0 +1,25 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+
+/* ---- Per instance Attribs ---- */
+in vec3 color;
+in float start;
+in float end;
+in mat4 InstanceModelMatrix;
+
+uniform float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ float len = end - start;
+ vec3 sta = vec3(0.0, 0.0, -start);
+
+ gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * -len + sta, 1.0);
+ gl_PointSize = size;
+ finalColor = vec4(color, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
new file mode 100644
index 00000000000..6f580ef3ff6
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl
@@ -0,0 +1,57 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. This geometry shader
+// decides which edge type to use if endpoints disagree.
+
+uniform mat4 ProjectionMatrix;
+
+uniform bool drawFront = true;
+uniform bool drawBack = true;
+uniform bool drawSilhouette = true;
+
+layout(lines) in;
+layout(line_strip, max_vertices = 2) out;
+
+in vec4 MV_pos[];
+in float edgeClass[];
+in vec3 fCol[];
+
+flat out vec4 finalColor;
+
+void emitLine(vec4 color)
+{
+ gl_Position = ProjectionMatrix * MV_pos[0];
+ EmitVertex();
+ gl_Position = ProjectionMatrix * MV_pos[1];
+ finalColor = color;
+ EmitVertex();
+ EndPrimitive();
+}
+
+void main()
+{
+ float finalEdgeClass = max(edgeClass[0], edgeClass[1]);
+
+ if (finalEdgeClass > 0.0f) {
+ // front-facing edge
+ if (drawFront)
+ emitLine(vec4(fCol[0], 0.75));
+ }
+ else if (finalEdgeClass < 0.0f) {
+ // back-facing edge
+ if (drawBack)
+ emitLine(vec4(fCol[0], 0.5));
+ }
+ else {
+ // exactly one face is front-facing, silhouette edge
+ if (drawSilhouette)
+ emitLine(vec4(fCol[0], 1.0));
+ }
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
new file mode 100644
index 00000000000..5d1e949c1d4
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl
@@ -0,0 +1,64 @@
+
+// Draw "fancy" wireframe, displaying front-facing, back-facing and
+// silhouette lines differently.
+// Mike Erwin, April 2015
+
+// After working with this shader a while, convinced we should make
+// separate shaders for perpective & ortho. (Oct 2016)
+
+// Due to perspective, the line segment's endpoints might disagree on
+// whether the adjacent faces are front facing. We use a geometry
+// shader to resolve this properly.
+
+uniform mat4 ViewMatrix;
+
+in vec3 pos;
+in vec3 N1, N2; // normals of faces this edge joins (object coords)
+
+/* instance attrib */
+in vec3 color;
+in mat4 InstanceModelMatrix;
+
+out vec4 MV_pos;
+out float edgeClass;
+out vec3 fCol;
+
+// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley
+
+mat3 NormalMatrix;
+
+bool front(vec3 N, vec3 eye)
+{
+ return dot(NormalMatrix * N, eye) > 0.0;
+}
+
+void main()
+{
+ vec3 eye;
+
+ mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix;
+
+ MV_pos = ModelViewMatrix * vec4(pos, 1.0);
+
+ NormalMatrix = transpose(inverse(mat3(ModelViewMatrix)));
+
+ /* if persp */
+ if (ViewMatrix[3][3] == 0.0) {
+ eye = normalize(-MV_pos.xyz);
+ }
+ else {
+ eye = vec3(0.0, 0.0, 1.0);
+ }
+
+ bool face_1_front = front(N1, eye);
+ bool face_2_front = front(N2, eye);
+
+ if (face_1_front && face_2_front)
+ edgeClass = 1.0; // front-facing edge
+ else if (face_1_front || face_2_front)
+ edgeClass = 0.0; // exactly one face is front-facing, silhouette edge
+ else
+ edgeClass = -1.0; // back-facing edge
+
+ fCol = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
new file mode 100644
index 00000000000..ce82dc6af2a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewMatrix;
+uniform mat4 ViewProjectionMatrix;
+uniform mat4 ModelMatrix;
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos;
+in vec3 nor;
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+out vec3 normal;
+flat out vec4 finalColor;
+
+void main()
+{
+ mat4 FinalModelMatrix = ModelMatrix * InstanceModelMatrix;
+ mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * FinalModelMatrix;
+ /* This is slow and run per vertex, but it's still faster than
+ * doing it per instance on CPU and sending it on via instance attrib */
+ mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * FinalModelMatrix)));
+
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+ normal = NormalMatrix * nor;
+
+ finalColor = color;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl
new file mode 100644
index 00000000000..a39bfde41ee
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl
@@ -0,0 +1,29 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instanciated Attribs ---- */
+in vec3 pos; /* using Z as axis id */
+
+/* ---- Per instance Attribs ---- */
+in mat4 InstanceModelMatrix;
+in vec3 color;
+in float size;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ vec3 offset;
+
+ if (pos.z == 0.0)
+ offset = vec3(1.125, 0.0, 0.0);
+ else if (pos.z == 1.0)
+ offset = vec3(0.0, 1.125, 0.0);
+ else
+ offset = vec3(0.0, 0.0, 1.125);
+
+ vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+ gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(offset * size, 1.0) + vec4(screen_pos * size, 0.0));
+ finalColor = vec4(color, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
index 43a7e42153a..ebda79558c7 100644
--- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl
@@ -29,7 +29,7 @@ void main() {
float mid_stroke = 0.5 * (radii[1] + radii[2]);
- vec4 backgroundColor = vec4(finalColor.rgb, 0.0);
+ vec4 backgroundColor = vec4(finalOutlineColor.rgb, 0.0);
if (dist > mid_stroke)
fragColor = mix(finalOutlineColor, backgroundColor, smoothstep(radii[1], radii[0], dist));
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
index 69afefa685f..6f33491af55 100644
--- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
@@ -26,7 +26,7 @@ void main() {
gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
// pass through unchanged
- gl_PointSize = size;
+ gl_PointSize = size + pixel_fudge; // 0.5 pixel_fudge on either side
finalColor = color;
finalOutlineColor = outlineColor;
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 0f3ffa8244b..ef30f8ae6c5 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,3 +1,18 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat4 ModelViewMatrixInverse;
+uniform mat4 ProjectionMatrixInverse;
+uniform mat3 NormalMatrix;
+
+#if __VERSION__ == 120
+ #define fragColor gl_FragColor
+#else
+ out vec4 fragColor;
+ #define texture2D texture
+ #define textureCube texture
+#endif
+
/* Converters */
float convert_rgba_to_float(vec4 color)
@@ -177,7 +192,7 @@ void geom(
out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback)
{
local = co;
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
+ view = (ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0);
global = (viewinvmat * vec4(local, 1.0)).xyz;
orco = attorco;
uv_attribute(attuv, uv);
@@ -1413,8 +1428,8 @@ void mtex_bump_init_objspace(
out float fPrevMagnitude_out, out vec3 vNacc_out,
out vec3 vR1, out vec3 vR2, out float fDet)
{
- mat3 obj2view = to_mat3(gl_ModelViewMatrix);
- mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse);
+ mat3 obj2view = to_mat3(ModelViewMatrix);
+ mat3 view2obj = to_mat3(ModelViewMatrixInverse);
vec3 vSigmaS = view2obj * dFdx(surf_pos);
vec3 vSigmaT = view2obj * dFdy(surf_pos);
@@ -1670,7 +1685,7 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
{
- outnormal = normalize(gl_NormalMatrix * texnormal);
+ outnormal = normalize(NormalMatrix * texnormal);
}
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
@@ -1794,7 +1809,7 @@ void lamp_visibility_clamp(float visifac, out float outvisifac)
void world_paper_view(vec3 vec, out vec3 outvec)
{
vec3 nvec = normalize(vec);
- outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0);
+ outvec = (ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0);
}
void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac)
@@ -1828,7 +1843,7 @@ void world_blend(vec3 vec, out float blend)
void shade_view(vec3 co, out vec3 view)
{
/* handle perspective/orthographic */
- view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
+ view = (ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0);
}
void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn)
@@ -2346,7 +2361,7 @@ void shade_mist_factor(
if (enable == 1.0) {
float fac, zcor;
- zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
+ zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2];
fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
if (misttype == 0.0) fac *= fac;
@@ -2605,11 +2620,11 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
- worldvec = (gl_ModelViewMatrixInverse * co).xyz;
+ worldvec = (ModelViewMatrixInverse * co).xyz;
}
void node_background(vec4 color, float strength, vec3 N, out vec4 result)
@@ -2634,7 +2649,7 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader)
void node_fresnel(float ior, vec3 N, vec3 I, out float result)
{
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
float eta = max(ior, 0.00001);
result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
@@ -2646,7 +2661,7 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
@@ -2700,7 +2715,7 @@ void node_geometry(
true_normal = normal;
/* handle perspective/orthographic */
- vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
incoming = -(toworld * vec4(I_view, 0.0)).xyz;
parametric = vec3(0.0);
@@ -2719,7 +2734,7 @@ void node_tex_coord(
uv = attr_uv;
object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz;
camera = vec3(I.xy, -I.z);
- vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
+ vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
vec3 shade_I;
@@ -2734,13 +2749,13 @@ void node_tex_coord_background(
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (gl_ProjectionMatrixInverse * v);
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
co = normalize(co);
- vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+ vec3 coords = (ModelViewMatrixInverse * co).xyz;
generated = coords;
normal = -coords;
@@ -2748,7 +2763,7 @@ void node_tex_coord_background(
object = coords;
camera = vec3(co.xy, -co.z);
- window = (gl_ProjectionMatrix[3][3] == 0.0) ?
+ window = (ProjectionMatrix[3][3] == 0.0) ?
vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) :
vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0);
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
index 8c8d81f6997..8c8d81f6997 100644
--- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
index f83785de95e..f83785de95e 100644
--- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
index d6cbe2d9a22..d6cbe2d9a22 100644
--- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
index b485d2cce86..d7cdec9441d 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl
@@ -1,16 +1,25 @@
uniform vec2 ScaleU;
uniform sampler2D textureSource;
+#if __VERSION__ == 120
+ varying vec2 texCoord_interp;
+ #define fragColor gl_FragColor
+#else
+ in vec2 texCoord_interp;
+ out vec4 fragColor;
+ #define texture2D texture
+#endif
+
void main()
{
vec4 color = vec4(0.0);
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
- color += texture2D(textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(0.0, 0.0)) * 0.3125;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375;
+ color += texture2D(textureSource, texCoord_interp.st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625;
- gl_FragColor = color;
+ fragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
index 5d00108b052..a0e5b022e67 100644
--- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl
@@ -1,6 +1,18 @@
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ attribute vec2 pos;
+ attribute vec2 uvs;
+ varying vec2 texCoord_interp;
+#else
+ in vec2 pos;
+ in vec2 uvs;
+ out vec2 texCoord_interp;
+#endif
+
void main()
{
- gl_Position = ftransform();
- gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);
+ texCoord_interp = uvs;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
index 9828787fb04..4eacd08d5af 100644
--- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl
@@ -1,12 +1,21 @@
+#ifndef USE_INSTANCE_COLOR
uniform vec4 color;
+#endif
uniform vec3 light;
#if __VERSION__ == 120
varying vec3 normal;
+#ifdef USE_INSTANCE_COLOR
+ varying vec4 finalColor;
+#endif
#define fragColor gl_FragColor
#else
in vec3 normal;
+#ifdef USE_INSTANCE_COLOR
+ flat in vec4 finalColor;
+ #define color finalColor
+#endif
out vec4 fragColor;
#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
new file mode 100644
index 00000000000..260539f76d7
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl
@@ -0,0 +1,17 @@
+
+uniform vec3 light;
+
+#if __VERSION__ == 120
+ varying vec3 normal;
+ varying vec4 finalColor;
+ #define fragColor gl_FragColor
+#else
+ in vec3 normal;
+ in vec4 finalColor;
+ out vec4 fragColor;
+#endif
+
+void main()
+{
+ fragColor = finalColor * max(0.0, dot(normalize(normal), light));
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
index 6ded453225e..fcb385ed30a 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl
@@ -1,5 +1,13 @@
-varying vec3 coords;
+#if __VERSION__ == 120
+ varying vec3 coords;
+ #define fragColor gl_FragColor
+#else
+ in vec3 coords;
+ out vec4 fragColor;
+ #define texture1D texture
+ #define texture3D texture
+#endif
uniform vec3 active_color;
uniform float step_size;
@@ -44,5 +52,5 @@ void main()
vec4 color = transfer_function * density_scale;
#endif
- gl_FragColor = color;
+ fragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
index 297486ae26a..f49272d0913 100644
--- a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl
@@ -1,5 +1,11 @@
-varying vec3 coords;
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ varying vec3 coords;
+#else
+ out vec3 coords;
+#endif
uniform vec3 min_location;
uniform vec3 invsize;
@@ -7,6 +13,6 @@ uniform vec3 ob_sizei;
void main()
{
- gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
+ gl_Position = ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0);
coords = (gl_Vertex.xyz - min_location) * invsize;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index db0068d2f3d..5a6b237b3be 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -1,3 +1,8 @@
+
+uniform mat4 ModelViewMatrix;
+uniform mat4 ProjectionMatrix;
+uniform mat3 NormalMatrix;
+
#ifdef USE_OPENSUBDIV
in vec3 normal;
in vec4 position;
@@ -7,8 +12,13 @@ out block {
} outpt;
#endif
-varying vec3 varposition;
-varying vec3 varnormal;
+#if __VERSION__ == 120
+ varying vec3 varposition;
+ varying vec3 varnormal;
+#else
+ out vec3 varposition;
+ out vec3 varnormal;
+#endif
#ifdef CLIP_WORKAROUND
varying float gl_ClipDistance[6];
@@ -89,11 +99,11 @@ void main()
vec3 normal = gl_Normal;
#endif
- vec4 co = gl_ModelViewMatrix * position;
+ vec4 co = ModelViewMatrix * position;
varposition = co.xyz;
- varnormal = normalize(gl_NormalMatrix * normal);
- gl_Position = gl_ProjectionMatrix * co;
+ varnormal = normalize(NormalMatrix * normal);
+ gl_Position = ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
int i;
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
index d45a4b316a8..7a39c3fc674 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -1,7 +1,11 @@
-varying vec3 varposition;
-varying vec3 varnormal;
-
+#if __VERSION__ == 120
+ varying vec3 varposition;
+ varying vec3 varnormal;
+#else
+ out vec3 varposition;
+ out vec3 varnormal;
+#endif
/* Color, keep in sync with: gpu_shader_vertex.glsl */
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
index 3761bf350eb..9035a311ecb 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl
@@ -2,7 +2,13 @@
* This fragment shader was initially found at http://fabiensanglard.net/shadowmappingVSM/index.php
*/
-varying vec4 v_position;
+#if __VERSION__ == 120
+ varying vec4 v_position;
+ #define fragColor gl_FragColor
+#else
+ in vec4 v_position;
+ out vec4 fragColor;
+#endif
void main()
{
@@ -17,5 +23,6 @@ void main()
float dy = dFdy(depth);
moment2 += 0.25 * (dx * dx + dy * dy);
- gl_FragColor = vec4(moment1, moment2, 0.0, 0.0);
+ fragColor = vec4(moment1, moment2, 0.0, 0.0);
+ // TODO: write to a 2-component target --^
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
index 224c3e78adc..96ea22b3483 100644
--- a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl
@@ -1,7 +1,14 @@
-varying vec4 v_position;
+
+uniform mat4 ModelViewProjectionMatrix;
+
+#if __VERSION__ == 120
+ varying vec4 v_position;
+#else
+ out vec4 v_position;
+#endif
void main()
{
- gl_Position = ftransform();
+ gl_Position = ModelViewProjectionMatrix * gl_Vertex;
v_position = gl_Position;
}
diff --git a/source/blender/imbuf/intern/imbuf.h b/source/blender/imbuf/intern/imbuf.h
index 897a149a45c..90dad70fa61 100644
--- a/source/blender/imbuf/intern/imbuf.h
+++ b/source/blender/imbuf/intern/imbuf.h
@@ -67,8 +67,6 @@
# define BIG_LONG SWAP_LONG
#endif
-typedef unsigned char uchar;
-
#define IMB_DPI_DEFAULT 72.0f
#endif /* __IMBUF_H__ */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index 2c6f3d2fc66..9c3e194b78c 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -98,6 +98,15 @@ enum {
IDP_STRING_SUB_BYTE = 1, /* arbitrary byte array, _not_ null terminated */
};
+/* IDP_GROUP */
+enum {
+ IDP_GROUP_SUB_NONE = 0, /* default */
+ IDP_GROUP_SUB_MODE_OBJECT = 1, /* object mode settings */
+ IDP_GROUP_SUB_MODE_EDIT = 2, /* mesh edit mode settings */
+ IDP_GROUP_SUB_ENGINE_RENDER = 3, /* render engine settings */
+ IDP_GROUP_SUB_OVERRIDE = 4, /* data override */
+};
+
/*->flag*/
enum {
IDP_FLAG_GHOST = 1 << 7, /* this means the property is set but RNA will return false when checking
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 1083400ece2..cc64ce92881 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -238,6 +238,8 @@ typedef struct bPoseChannel {
float chan_mat[4][4]; /* matrix result of loc/quat/size, and where we put deform in, see next line */
float pose_mat[4][4]; /* constraints accumulate here. in the end, pose_mat = bone->arm_mat * chan_mat
* this matrix is object space */
+ float disp_mat[4][4]; /* for display, pose_mat with bone length applied */
+ float disp_tail_mat[4][4]; /* for display, pose_mat with bone length applied and translated to tail*/
float constinv[4][4]; /* inverse result of constraints.
* doesn't include effect of restposition, parent, and local transform*/
diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h
index 52e40cbc098..4aa3edcc788 100644
--- a/source/blender/makesdna/DNA_camera_types.h
+++ b/source/blender/makesdna/DNA_camera_types.h
@@ -85,6 +85,13 @@ typedef struct Camera {
char sensor_fit;
char pad[7];
+ /* runtime only, used for drawing */
+ float drwcorners[4][2];
+ float drwtria[2][2];
+ float drwdepth, pad1;
+ float drwfocusmat[4][4];
+ float drwnormalmat[4][4];
+
/* Stereo settings */
struct CameraStereoSettings stereo;
} Camera;
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index bb526c41049..ba1bf1520ce 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -126,7 +126,7 @@ typedef enum eGPDpalettecolor_Flag {
PC_COLOR_LOCKED = (1 << 2),
/* do onion skinning */
PC_COLOR_ONIONSKIN = (1 << 3),
- /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ /* "volumetric" strokes */
PC_COLOR_VOLUMETRIC = (1 << 4),
/* Use High quality fill */
PC_COLOR_HQ_FILL = (1 << 5)
@@ -271,7 +271,7 @@ typedef enum eGPDlayer_Flag {
GP_LAYER_GHOST_PREVCOL = (1 << 8),
/* use custom color for ghosts after current frame */
GP_LAYER_GHOST_NEXTCOL = (1 << 9),
- /* "volumetric" strokes (i.e. GLU Quadric discs in 3D) */
+ /* "volumetric" strokes */
GP_LAYER_VOLUMETRIC = (1 << 10),
/* Use high quality fill (instead of buggy legacy OpenGL Fill) */
GP_LAYER_HQ_FILL = (1 << 11),
diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h
index bd456b526c7..6fe3a9f1c8a 100644
--- a/source/blender/makesdna/DNA_layer_types.h
+++ b/source/blender/makesdna/DNA_layer_types.h
@@ -43,6 +43,7 @@ typedef struct Base {
unsigned int lay;
int flag_legacy;
int pad;
+ struct IDProperty *collection_properties; /* used by depsgraph, flushed from collection-tree */
} Base;
typedef struct CollectionOverride {
@@ -55,11 +56,14 @@ typedef struct LayerCollection {
struct LayerCollection *next, *prev;
struct SceneCollection *scene_collection;
short flag;
- short pad[3];
+ /* TODO(sergey): Get rid of this once we've got CoW in DEG, */
+ short flag_evaluated;
+ short pad[2];
ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
ListBase overrides;
ListBase layer_collections; /* synced with collection->collections */
- ListBase engine_settings; /* CollectionEngineSettings */
+ struct IDProperty *properties; /* overrides */
+ struct IDProperty *properties_evaluated;
} LayerCollection;
typedef struct SceneLayer {
@@ -98,7 +102,6 @@ enum {
enum {
COLLECTION_VISIBLE = (1 << 0),
COLLECTION_SELECTABLE = (1 << 1),
- COLLECTION_FOLDED = (1 << 2),
};
/* SceneLayer->flag */
@@ -111,43 +114,12 @@ enum {
/* *************************************************************** */
/* Engine Settings */
-typedef struct CollectionEngineProperty {
- struct CollectionEngineProperty *next, *prev;
- char name[64]; /* MAX_NAME */
- short type;
- short pad;
- char flag;
- char pad2[3];
-} CollectionEngineProperty;
-
-typedef struct CollectionEnginePropertyInt {
- struct CollectionEngineProperty data;
- int value;
- int pad;
-} CollectionEnginePropertyInt;
-
-typedef struct CollectionEnginePropertyFloat {
- struct CollectionEngineProperty data;
- float value;
- float pad;
-} CollectionEnginePropertyFloat;
-
-typedef struct CollectionEngineSettings {
- struct CollectionEngineSettings *next, *prev;
- char name[32]; /* engine name - MAX_NAME */
- ListBase properties; /* CollectionProperty */
-} CollectionEngineSettings;
-
-/* CollectionEngineProperty->flag */
-enum {
- COLLECTION_PROP_USE = (1 << 0),
-};
-
-/* CollectionEntineProperty.type */
-typedef enum CollectionEnginePropertyType {
- COLLECTION_PROP_TYPE_FLOAT = 0,
- COLLECTION_PROP_TYPE_INT = 1,
-} CollectionEnginePropertyType;
+/* CollectionEngineSettings->type */
+typedef enum CollectionEngineSettingsType {
+ COLLECTION_MODE_NONE = 0,
+ COLLECTION_MODE_OBJECT = 1,
+ COLLECTION_MODE_EDIT = 2,
+} CollectionModeSettingsType;
/* *************************************************************** */
diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index bd8278f897a..67bc49032d5 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -90,38 +90,11 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
-/* Material Engine Settings */
-typedef struct MaterialEngineSettings {
- struct MaterialEngineSettings *next, *prev;
- char name[32]; /* engine name - MAX_NAME */
- void *data;
-} MaterialEngineSettings;
-
/* Clay engine */
/* MaterialRuntimeClay.flag */
#define CLAY_OUTDATED 1
-typedef struct MaterialEngineSettingsClay {
- short type;
- short matcap_icon; /* Icon ID */
-
- float matcap_rot;
- float matcap_hue;
- float matcap_sat;
- float matcap_val;
-
- float ssao_distance;
- float ssao_attenuation;
- float ssao_factor_cavity;
- float ssao_factor_edge;
-
- /* Runtime */
- short flag;
- short pad;
- int ubo_index;
-} MaterialEngineSettingsClay;
-
/* MaterialEngineSettingsClay.type */
#define CLAY_MATCAP_NONE 0
#define CLAY_MATCAP_SIMPLE 1
@@ -240,9 +213,6 @@ typedef struct Material {
struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
* with refresh_texpaint_image_cache */
- /* Engine Settings */
- ListBase engines_settings; /* MaterialEngineSettings */
-
ListBase gpumaterial; /* runtime */
} Material;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index f95533a88f9..823a7f0812f 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -86,6 +86,7 @@ typedef enum ModifierType {
eModifierType_NormalEdit = 50,
eModifierType_CorrectiveSmooth = 51,
eModifierType_MeshSequenceCache = 52,
+ eModifierType_SurfaceDeform = 53,
NUM_MODIFIER_TYPES
} ModifierType;
@@ -276,6 +277,7 @@ typedef struct MirrorModifierData {
short axis DNA_DEPRECATED; /* deprecated, use flag instead */
short flag;
float tolerance;
+ float uv_offset[2];
struct Object *mirror_ob;
} MirrorModifierData;
@@ -1570,6 +1572,46 @@ enum {
MOD_MESHSEQ_READ_COLOR = (1 << 3),
};
+typedef struct SDefBind {
+ unsigned int *vert_inds;
+ unsigned int numverts;
+ int mode;
+ float *vert_weights;
+ float normal_dist;
+ float influence;
+} SDefBind;
+
+typedef struct SDefVert {
+ SDefBind *binds;
+ unsigned int numbinds;
+ char pad[4];
+} SDefVert;
+
+typedef struct SurfaceDeformModifierData {
+ ModifierData modifier;
+
+ struct Object *target; /* bind target object */
+ SDefVert *verts; /* vertex bind data */
+ float falloff;
+ unsigned int numverts, numpoly;
+ int flags;
+ float mat[4][4];
+} SurfaceDeformModifierData;
+
+/* Surface Deform modifier flags */
+enum {
+ MOD_SDEF_BIND = (1 << 0),
+ MOD_SDEF_USES_LOOPTRI = (1 << 1),
+ MOD_SDEF_HAS_CONCAVE = (1 << 2),
+};
+
+/* Surface Deform vertex bind modes */
+enum {
+ MOD_SDEF_MODE_LOOPTRI = 0,
+ MOD_SDEF_MODE_NGON = 1,
+ MOD_SDEF_MODE_CENTROID = 2,
+};
+
#define MOD_MESHSEQ_READ_ALL \
(MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index fd601e55550..47677e50451 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -668,7 +668,8 @@ typedef struct NodeScriptDict {
/* qdn: glare node */
typedef struct NodeGlare {
char quality, type, iter;
- char angle, pad_c1, size, pad[2];
+ /* XXX angle is only kept for backward/forward compatibility, was used for two different things, see T50736. */
+ char angle DNA_DEPRECATED, pad_c1, size, star_45, streaks;
float colmod, mix, threshold, fade;
float angle_ofs, pad_f1;
} NodeGlare;
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 59acefeffe4..ed14c4b9311 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -372,6 +372,7 @@ typedef struct SoftBody {
#define PFIELD_DO_ROTATION (1<<15)
#define PFIELD_GUIDE_PATH_WEIGHT (1<<16) /* apply curve weights */
#define PFIELD_SMOKE_DENSITY (1<<17) /* multiply smoke force by density */
+#define PFIELD_GRAVITATION (1<<18) /* used for (simple) force */
/* pd->falloff */
#define PFIELD_FALL_SPHERE 0
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index b92d2cd1573..71d05e41c43 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -46,7 +46,6 @@ struct Object;
struct AnimData;
struct Ipo;
struct BoundBox;
-struct CollectionEngineSettings;
struct Path;
struct Material;
struct PartDeflect;
@@ -304,7 +303,9 @@ typedef struct Object {
struct PreviewImage *preview;
- struct CollectionEngineSettings *collection_settings; /* used by depsgraph, flushed from collection-tree */
+ struct IDProperty *base_collection_properties; /* used by depsgraph, flushed from base */
+
+ ListBase drawdata; /* runtime, for draw engine datas */
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 8c9de0665c4..cb868ceb98e 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -38,6 +38,9 @@ struct ID;
typedef struct TreeStoreElem {
short type, nr, flag, used;
+
+ /* XXX We actually also store non-ID data in this pointer for identifying
+ * the TreeStoreElem for a TreeElement when rebuilding the tree. Ugly! */
struct ID *id;
} TreeStoreElem;
@@ -99,7 +102,8 @@ enum {
#define TSE_KEYMAP_ITEM 35 /* NO ID */
#define TSE_ID_BASE 36 /* NO ID */
#define TSE_GP_LAYER 37 /* NO ID */
-#define TSE_COLLECTION 38 /* NO ID */
+#define TSE_LAYER_COLLECTION 38 /* NO ID */
+#define TSE_SCENE_COLLECTION 39 /* NO ID */
/* Check whether given TreeStoreElem should have a real ID in its ->id member. */
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8eb1d3f5da8..3f646f80f36 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -539,44 +539,6 @@ typedef enum BakePassFilter {
#define R_BAKE_PASS_FILTER_ALL (~0)
-/* *************************************************************** */
-/* Engine Settings */
-
-typedef struct RenderEngineSettings {
- struct RenderEngineSettings *next, *prev;
- char name[32]; /* engine name */
- void *data;
-} RenderEngineSettings;
-
-/* Render Data */
-typedef struct RenderEngineSettingsClay {
- /* Use same layout as MaterialEngineSettingsClay so this struct
- * can be used as Material Settings. */
- short type;
- short matcap_icon; /* Icon ID */
-
- float matcap_rot;
- float matcap_hue;
- float matcap_sat;
- float matcap_val;
-
- float ssao_distance;
- float ssao_attenuation;
- float ssao_factor_cavity;
- float ssao_factor_edge;
-
- short flag;
- short pad;
- int ubo_index;
- /* end of MaterialEngineSettingsClay */
-
- /* Global Settings */
- short options;
- short pad1;
- int ssao_samples;
- int pad2[2];
-} RenderEngineSettingsClay;
-
/* RenderEngineSettingsClay.options */
typedef enum ClayFlagSettings {
CLAY_USE_AO = (1 << 0),
@@ -1115,6 +1077,7 @@ typedef struct ParticleEditSettings {
int draw_step, fade_frames;
struct Scene *scene;
+ struct SceneLayer *scene_layer;
struct Object *object;
struct Object *shape_object;
} ParticleEditSettings;
@@ -1751,7 +1714,7 @@ typedef struct Scene {
int active_layer;
int pad4;
- ListBase engines_settings; /* RenderEngineSettings */
+ IDProperty *collection_properties; /* settings to be overriden by layer collections */
int pad5[2];
} Scene;
@@ -1763,6 +1726,7 @@ typedef struct Scene {
#define SCER_LOCK_FRAME_SELECTION (1<<1)
/* timeline/keyframe jumping - only selected items (on by default) */
#define SCE_KEYS_NO_SELONLY (1<<2)
+#define SCER_SHOW_SUBFRAME (1<<3)
/* mode (int now) */
#define R_OSA 0x0001
@@ -1963,11 +1927,6 @@ extern const char *RE_engine_id_CYCLES;
((base)->flag_legacy & SELECT) && \
((base)->lay & v3d->lay) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define TESTBASELIB(v3d, base) ( \
- ((base)->flag_legacy & SELECT) && \
- ((base)->lay & v3d->lay) && \
- ((base)->object->id.lib == NULL) && \
- (((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
#define TESTBASELIB_BGMODE(v3d, scene, base) ( \
((base)->flag_legacy & SELECT) && \
((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
@@ -1977,40 +1936,37 @@ extern const char *RE_engine_id_CYCLES;
((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
((base)->object->id.lib == NULL) && \
(((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0))
-#define BASE_SELECTABLE(v3d, base) ( \
- (v3d != NULL) && \
- (base->object->restrictflag & (OB_RESTRICT_SELECT | OB_RESTRICT_VIEW)) == 0)
-#define BASE_VISIBLE(v3d, base) ( \
- (base->lay & v3d->lay) && \
- (base->object->restrictflag & OB_RESTRICT_VIEW) == 0)
#define BASE_VISIBLE_BGMODE(v3d, scene, base) ( \
- (base->lay & (v3d ? v3d->lay : scene->lay)) && \
- (base->object->restrictflag & OB_RESTRICT_VIEW) == 0)
+ ((base)->lay & (v3d ? v3d->lay : scene->lay)) && \
+ ((base)->object->restrictflag & OB_RESTRICT_VIEW) == 0)
+#define TESTBASE_NEW(base) ( \
+ (((base)->flag & BASE_SELECTED) != 0) && \
+ (((base)->flag & BASE_VISIBLED) != 0))
#define TESTBASELIB_NEW(base) ( \
- ((base->flag & BASE_SELECTED) != 0) && \
+ (((base)->flag & BASE_SELECTED) != 0) && \
((base)->object->id.lib == NULL) && \
- ((base->flag & BASE_VISIBLED) != 0))
+ (((base)->flag & BASE_VISIBLED) != 0))
#define TESTBASELIB_BGMODE_NEW(base) ( \
- ((base->flag & BASE_SELECTED) != 0) && \
- (base->object->id.lib == NULL) && \
- ((base->flag & BASE_VISIBLED) != 0))
+ (((base)->flag & BASE_SELECTED) != 0) && \
+ ((base)->object->id.lib == NULL) && \
+ (((base)->flag & BASE_VISIBLED) != 0))
#define BASE_EDITABLE_BGMODE_NEW(base) ( \
((base)->object->id.lib == NULL) && \
- ((base->flag & BASE_VISIBLED) != 0))
+ (((base)->flag & BASE_VISIBLED) != 0))
#define BASE_SELECTABLE_NEW(base) \
- ((base->flag & BASE_SELECTABLED) != 0)
+ (((base)->flag & BASE_SELECTABLED) != 0)
#define BASE_VISIBLE_NEW(base) ( \
- (base->flag & BASE_VISIBLED) != 0)
+ ((base)->flag & BASE_VISIBLED) != 0)
#define FIRSTBASE scene->base.first
#define LASTBASE scene->base.last
#define BASACT (scene->basact)
#define OBACT (BASACT ? BASACT->object: NULL)
-#define FIRSTBASE_NEW sl->object_bases.first
-#define LASTBASE_NEW sl->object_bases.last
-#define BASACT_NEW (sl->basact)
+#define FIRSTBASE_NEW (sl)->object_bases.first
+#define LASTBASE_NEW (sl)->object_bases.last
+#define BASACT_NEW ((sl)->basact)
#define OBACT_NEW (BASACT_NEW ? BASACT_NEW->object: NULL)
#define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL)
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 3524c041069..10f41408f48 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -289,7 +289,8 @@ typedef enum eSpaceOutliner_Mode {
SO_USERDEF = 12,
/* SO_KEYMAP = 13, */ /* deprecated! */
SO_ID_ORPHANS = 14,
- SO_COLLECTIONS = 15,
+ SO_ACT_LAYER = 15,
+ SO_COLLECTIONS = 16,
} eSpaceOutliner_Mode;
/* SpaceOops->storeflag */
@@ -1345,20 +1346,6 @@ typedef enum eSpaceClip_GPencil_Source {
SC_GPENCIL_SRC_TRACK = 1,
} eSpaceClip_GPencil_Source;
-/* Collection Manager ======================================= */
-
-typedef struct SpaceCollections {
- SpaceLink *next, *prev;
- ListBase regionbase; /* storage of regions for inactive spaces */
- int spacetype;
- int flag; /* eSpaceCollections_Flag */
-} SpaceCollections;
-
-/* SpaceClip->flag */
-typedef enum eSpaceCollections_Flag {
- SC_COLLECTION_DATA_REFRESH = (1 << 0), /* recreate/update SpaceCollections layer data, needed for undo/read/write */
-} eSpaceCollections_Flag;
-
/* **************** SPACE DEFINES ********************* */
/* space types, moved from DNA_screen_types.h */
@@ -1388,9 +1375,8 @@ typedef enum eSpace_Type {
SPACE_CONSOLE = 18,
SPACE_USERPREF = 19,
SPACE_CLIP = 20,
- SPACE_COLLECTIONS = 21,
-
- SPACEICONMAX = SPACE_COLLECTIONS
+
+ SPACEICONMAX = SPACE_CLIP
} eSpace_Type;
/* use for function args */
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 6cc24f74cee..82a56af9386 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -161,7 +161,7 @@ typedef struct ThemeUI {
/* Interface Elements (buttons, menus, icons) */
uiWidgetColors wcol_regular, wcol_tool, wcol_text;
uiWidgetColors wcol_radio, wcol_option, wcol_toggle;
- uiWidgetColors wcol_num, wcol_numslider;
+ uiWidgetColors wcol_num, wcol_numslider, wcol_tab;
uiWidgetColors wcol_menu, wcol_pulldown, wcol_menu_back, wcol_menu_item, wcol_tooltip;
uiWidgetColors wcol_box, wcol_scroll, wcol_progress, wcol_list_item, wcol_pie_menu;
@@ -390,8 +390,7 @@ typedef struct bTheme {
ThemeSpace tuserpref;
ThemeSpace tconsole;
ThemeSpace tclip;
- ThemeSpace tcollections;
-
+
/* 20 sets of bone colors for this theme */
ThemeWireColor tarm[20];
/*ThemeWireColor tobj[20];*/
@@ -468,13 +467,18 @@ typedef struct UserDef {
int audioformat;
int audiochannels;
- int scrollback; /* console scrollback limit */
- int dpi; /* range 48-128? */
- char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
+ int scrollback; /* console scrollback limit */
+ int dpi; /* range 48-128? */
+ float ui_scale; /* interface scale */
+ int pad1;
+ char node_margin; /* node insert offset (aka auto-offset) margin, but might be useful for later stuff as well */
char pad2;
short transopts;
short menuthreshold1, menuthreshold2;
-
+
+ /* startup template */
+ char app_template[64];
+
struct ListBase themes;
struct ListBase uifonts;
struct ListBase uistyles;
@@ -499,7 +503,6 @@ typedef struct UserDef {
int prefetchframes;
float pad_rot_angle; /* control the rotation step of the view when PAD2, PAD4, PAD6&PAD8 is use */
short frameserverport;
- short pad4;
short obcenter_dia;
short rvisize; /* rotating view icon size */
short rvibright; /* rotating view icon brightness */
@@ -511,6 +514,8 @@ typedef struct UserDef {
char ipo_new; /* interpolation mode for newly added F-Curves */
char keyhandles_new; /* handle types for newly added keyframes */
char gpu_select_method;
+ char gpu_select_pick_deph;
+ char pad4;
char view_frame_type;
int view_frame_keyframes; /* number of keyframes to zoom around current frame */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 5fd4c9fd407..f3d3faecbb4 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -128,6 +128,7 @@ typedef struct World {
/* nodes */
struct bNodeTree *nodetree;
+ float mistend, pad1; /* runtime : miststa + mistdist, used for drawing camera */
ListBase gpumaterial; /* runtime */
} World;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 2221526fa8b..e8cb54448de 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -386,8 +386,6 @@ extern StructRNA RNA_MaterialStrand;
extern StructRNA RNA_MaterialSubsurfaceScattering;
extern StructRNA RNA_MaterialTextureSlot;
extern StructRNA RNA_MaterialVolume;
-extern StructRNA RNA_MaterialEngineSettings;
-extern StructRNA RNA_MaterialEngineSettingsClay;
extern StructRNA RNA_Mask;
extern StructRNA RNA_MaskLayer;
extern StructRNA RNA_Menu;
@@ -581,7 +579,6 @@ extern StructRNA RNA_SpaceFileBrowser;
extern StructRNA RNA_SpaceGraphEditor;
extern StructRNA RNA_SpaceImageEditor;
extern StructRNA RNA_SpaceInfo;
-extern StructRNA RNA_SpaceCollectionManager;
extern StructRNA RNA_SpaceLogicEditor;
extern StructRNA RNA_SpaceNLA;
extern StructRNA RNA_SpaceNodeEditor;
@@ -607,6 +604,7 @@ extern StructRNA RNA_StucciTexture;
extern StructRNA RNA_SubsurfModifier;
extern StructRNA RNA_SunLamp;
extern StructRNA RNA_SurfaceCurve;
+extern StructRNA RNA_SurfaceDeformModifier;
extern StructRNA RNA_SurfaceModifier;
extern StructRNA RNA_TexMapping;
extern StructRNA RNA_Text;
@@ -650,7 +648,6 @@ extern StructRNA RNA_ThemeFontStyle;
extern StructRNA RNA_ThemeGraphEditor;
extern StructRNA RNA_ThemeImageEditor;
extern StructRNA RNA_ThemeInfo;
-extern StructRNA RNA_ThemeCollectionManager;
extern StructRNA RNA_ThemeLogicEditor;
extern StructRNA RNA_ThemeNLAEditor;
extern StructRNA RNA_ThemeNodeEditor;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 1c9b3593d17..b9bb741bcde 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -61,6 +61,7 @@ extern EnumPropertyItem rna_enum_object_modifier_type_items[];
extern EnumPropertyItem rna_enum_constraint_type_items[];
extern EnumPropertyItem rna_enum_boidrule_type_items[];
extern EnumPropertyItem rna_enum_sequence_modifier_type_items[];
+extern EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[];
extern EnumPropertyItem rna_enum_modifier_triangulate_quad_method_items[];
extern EnumPropertyItem rna_enum_modifier_triangulate_ngon_method_items[];
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 0c4c7ddac81..d398ce95a52 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -34,6 +34,8 @@
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "BKE_action.h"
#include "RNA_access.h"
@@ -731,6 +733,7 @@ static void rna_def_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "ID Root Type",
"Type of ID block that action can be used on - "
"DO NOT CHANGE UNLESS YOU KNOW WHAT YOU ARE DOING");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
/* API calls */
RNA_api_action(srna);
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 9adbf5f6b2e..f271bccd326 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -32,6 +32,8 @@
#include "BLI_utildefines.h"
+#include "BLT_translation.h"
+
#include "MEM_guardedalloc.h"
#include "RNA_access.h"
@@ -742,6 +744,7 @@ static void rna_def_keyingset_path(BlenderRNA *brna)
RNA_def_property_enum_default(prop, ID_OB);
RNA_def_property_enum_funcs(prop, NULL, "rna_ksPath_id_type_set", NULL);
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET | NA_EDITED, NULL); /* XXX: maybe a bit too noisy */
/* Group */
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 07d295c8bbc..891f5c43ca6 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -187,6 +187,9 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
}
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
+
+ /* spaces that show animation data of the selected bone need updating */
+ WM_main_add_notifier(NC_ANIMATION | ND_ANIMCHAN, id);
}
static char *rna_Bone_path(PointerRNA *ptr)
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index ac348c1750c..a51e7bfe6d8 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -360,17 +360,19 @@ static void rna_Brush_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
/*WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D, NULL); */
}
-static void rna_Brush_main_tex_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Brush_main_tex_update(Main *bmain, bContext *C, Scene *scene, PointerRNA *ptr)
{
+ SceneLayer *sl = CTX_data_scene_layer(C);
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, br->mtex.tex);
+ BKE_paint_invalidate_overlay_tex(scene, sl, br->mtex.tex);
rna_Brush_update(bmain, scene, ptr);
}
-static void rna_Brush_secondary_tex_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Brush_secondary_tex_update(Main *bmain, bContext *C, Scene *scene, PointerRNA *ptr)
{
+ SceneLayer *sl = CTX_data_scene_layer(C);
Brush *br = (Brush *)ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, br->mask_mtex.tex);
+ BKE_paint_invalidate_overlay_tex(scene, sl, br->mask_mtex.tex);
rna_Brush_update(bmain, scene, ptr);
}
@@ -426,14 +428,16 @@ static void rna_Brush_icon_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
-static void rna_TextureSlot_brush_angle_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_TextureSlot_brush_angle_update(Main *bmain, bContext *C, Scene *scene, PointerRNA *ptr)
{
MTex *mtex = ptr->data;
/* skip invalidation of overlay for stencil mode */
- if (mtex->mapping != MTEX_MAP_MODE_STENCIL)
- BKE_paint_invalidate_overlay_tex(scene, mtex->tex);
+ if (mtex->mapping != MTEX_MAP_MODE_STENCIL) {
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ BKE_paint_invalidate_overlay_tex(scene, sl, mtex->tex);
+ }
- rna_TextureSlot_update(bmain, scene, ptr);
+ rna_TextureSlot_update(bmain, C, scene, ptr);
}
static void rna_Brush_set_size(PointerRNA *ptr, int value)
@@ -647,39 +651,46 @@ static void rna_def_brush_texture_slot(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "rot");
RNA_def_property_range(prop, 0, M_PI * 2);
RNA_def_property_ui_text(prop, "Angle", "Brush texture rotation");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_brush_angle_update");
prop = RNA_def_property(srna, "map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "tex_paint_map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_tex_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "mask_map_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "brush_map_mode");
RNA_def_property_enum_items(prop, prop_mask_paint_map_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_rake", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RAKE);
RNA_def_property_ui_text(prop, "Rake", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_random", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "brush_angle_mode", MTEX_ANGLE_RANDOM);
RNA_def_property_ui_text(prop, "Random", "");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "random_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, 0, M_PI * 2);
RNA_def_property_ui_text(prop, "Random Angle", "Brush texture random angle");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
TEXTURE_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source");
@@ -1338,7 +1349,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mtex.tex");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_main_tex_update");
@@ -1350,7 +1361,7 @@ static void rna_def_brush(BlenderRNA *brna)
prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mask_mtex.tex");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Mask Texture", "");
RNA_def_property_update(prop, NC_TEXTURE, "rna_Brush_secondary_tex_update");
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index dc97d39052b..1d232d2df39 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -3157,8 +3157,9 @@ int rna_parameter_size(PropertyRNA *parm)
StringPropertyRNA *sparm = (StringPropertyRNA *)parm;
return sizeof(char) * sparm->maxlength;
}
- else
+ else {
return sizeof(char *);
+ }
case PROP_POINTER:
{
#ifdef RNA_RUNTIME
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 4acdee490b8..bccc47aa95d 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -35,6 +35,8 @@
#include "BLI_math.h"
+#include "BLT_translation.h"
+
#include "BKE_action.h"
#include "RNA_access.h"
@@ -1448,6 +1450,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_enum_funcs(prop, NULL, "rna_DriverTarget_id_type_set", NULL);
RNA_def_property_editable_func(prop, "rna_DriverTarget_id_type_editable");
RNA_def_property_ui_text(prop, "ID Type", "Type of ID-block that can be used");
+ RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
/* Target Properties - Property to Drive */
diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c
index bb927603e46..936674a1e96 100644
--- a/source/blender/makesrna/intern/rna_image_api.c
+++ b/source/blender/makesrna/intern/rna_image_api.c
@@ -56,9 +56,6 @@
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
-#include "GPU_draw.h"
-#include "GPU_debug.h"
-
#include "DNA_image_types.h"
#include "DNA_scene_types.h"
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index b904b65a37a..c79f6c3bd9a 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -236,7 +236,7 @@ int rna_object_shapekey_index_set(struct ID *id, PointerRNA value, int current);
/* named internal so as not to conflict with obj.update() rna func */
void rna_Object_internal_update_data(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
void rna_Mesh_update_draw(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
-void rna_TextureSlot_update(struct Main *bmain, struct Scene *scene, struct PointerRNA *ptr);
+void rna_TextureSlot_update(struct Main *bmain, struct bContext *C, struct Scene *scene, struct PointerRNA *ptr);
/* basic poll functions for object types */
int rna_Armature_object_poll(struct PointerRNA *ptr, struct PointerRNA value);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 4d3e3ffca26..b293f20dd95 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -313,31 +313,6 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value)
}
}
-static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr)
-{
-#ifdef WITH_CLAY_ENGINE
- MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data;
- if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) {
- return &RNA_MaterialEngineSettingsClay;
- }
-#endif
- return &RNA_MaterialEngineSettings;
-}
-
-static void rna_Material_update_engine_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
-{
-#if 0
- Material *ma = (Material *)ptr->data;
- RenderEngineSettings *ed = DRW_material_settings_get(ma, sce->r.engine, NULL);
-
- if (ed->runtime) {
- MEM_freeN(ed->runtime);
- ed->runtime = NULL;
- }
-#endif
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-
static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value)
{
Material *ma = (Material *)ptr->data;
@@ -849,118 +824,6 @@ static void rna_def_material_mtex(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Material_update");
}
-static void rna_def_material_settings_clay(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- static EnumPropertyItem clay_matcap_items[] = {
- {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
- {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
- {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
- {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
- {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
- {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
- {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
- {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
- {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
- {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
- {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
- {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
- {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
- {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
- {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
- {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
- {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
- {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
- {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
- {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
- {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
- {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
- {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
- {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- static EnumPropertyItem clay_matcap_type[] = {
- {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
- {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
- {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "MaterialEngineSettingsClay", "MaterialEngineSettings");
- RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
- RNA_def_struct_sdna_from(srna, "MaterialEngineSettingsClay", "data");
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, clay_matcap_type);
- RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, clay_matcap_items);
- RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_val");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
- RNA_def_property_range(prop, 0.0f, 250.0f);
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
- RNA_def_property_range(prop, 0.0f, 250.0f);
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-
- prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
- RNA_def_property_range(prop, 1.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
- RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
-}
-
-static void rna_def_material_engine_settings(BlenderRNA *brna)
-{
- StructRNA *srna;
-
- srna = RNA_def_struct(brna, "MaterialEngineSettings", NULL);
- RNA_def_struct_ui_text(srna, "Engine Settings", "Engine specific settings");
- RNA_def_struct_sdna(srna, "MaterialEngineSettings");
- RNA_def_struct_refine_func(srna, "rna_MaterialEngineSettings_refine");
-
- rna_def_material_settings_clay(brna);
-}
-
static void rna_def_material_gamesettings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2224,11 +2087,6 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "MaterialGameSettings");
RNA_def_property_ui_text(prop, "Game Settings", "Game material settings");
- /* Engine settings */
- prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "MaterialEngineSettings");
- RNA_def_property_ui_text(prop, "Material Engine Settings", "Engine specific settings");
-
/* nodetree */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
@@ -2278,7 +2136,6 @@ void RNA_def_material(BlenderRNA *brna)
rna_def_material_strand(brna);
rna_def_material_physics(brna);
rna_def_material_gamesettings(brna);
- rna_def_material_engine_settings(brna);
RNA_api_material(srna);
}
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index ff9873fb3d1..9b0a25560f9 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -209,6 +209,11 @@ static void rna_Mesh_flip_normals(Mesh *mesh)
DAG_id_tag_update(&mesh->id, 0);
}
+static void rna_Mesh_split_faces(Mesh *mesh, int free_loop_normals)
+{
+ BKE_mesh_split_faces(mesh, free_loop_normals != 0);
+}
+
#else
void RNA_api_mesh(StructRNA *srna)
@@ -240,8 +245,10 @@ void RNA_api_mesh(StructRNA *srna)
func = RNA_def_function(srna, "free_normals_split", "rna_Mesh_free_normals_split");
RNA_def_function_ui_description(func, "Free split vertex normals");
- func = RNA_def_function(srna, "split_faces", "BKE_mesh_split_faces");
+ func = RNA_def_function(srna, "split_faces", "rna_Mesh_split_faces");
RNA_def_function_ui_description(func, "Split faces based on the edge angle");
+ RNA_def_boolean(func, "free_loop_normals", 1, "Free Loop Notmals",
+ "Free loop normals custom data layer");
func = RNA_def_function(srna, "calc_tangents", "rna_Mesh_calc_tangents");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index c4f0db38a16..1a8dd05a7b5 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -105,6 +105,7 @@ EnumPropertyItem rna_enum_object_modifier_type_items[] = {
{eModifierType_Shrinkwrap, "SHRINKWRAP", ICON_MOD_SHRINKWRAP, "Shrinkwrap", ""},
{eModifierType_SimpleDeform, "SIMPLE_DEFORM", ICON_MOD_SIMPLEDEFORM, "Simple Deform", ""},
{eModifierType_Smooth, "SMOOTH", ICON_MOD_SMOOTH, "Smooth", ""},
+ {eModifierType_SurfaceDeform, "SURFACE_DEFORM", ICON_MOD_MESHDEFORM, "Surface Deform", ""},
{eModifierType_Warp, "WARP", ICON_MOD_WARP, "Warp", ""},
{eModifierType_Wave, "WAVE", ICON_MOD_WAVE, "Wave", ""},
{0, "", 0, N_("Simulate"), ""},
@@ -408,6 +409,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr)
return &RNA_CorrectiveSmoothModifier;
case eModifierType_MeshSequenceCache:
return &RNA_MeshSequenceCacheModifier;
+ case eModifierType_SurfaceDeform:
+ return &RNA_SurfaceDeformModifier;
/* Default */
case eModifierType_None:
case eModifierType_ShapeKey:
@@ -573,6 +576,7 @@ RNA_MOD_OBJECT_SET(MeshDeform, object, OB_MESH);
RNA_MOD_OBJECT_SET(NormalEdit, target, OB_EMPTY);
RNA_MOD_OBJECT_SET(Shrinkwrap, target, OB_MESH);
RNA_MOD_OBJECT_SET(Shrinkwrap, auxTarget, OB_MESH);
+RNA_MOD_OBJECT_SET(SurfaceDeform, target, OB_MESH);
static void rna_HookModifier_object_set(PointerRNA *ptr, PointerRNA value)
{
@@ -1131,6 +1135,11 @@ static int rna_CorrectiveSmoothModifier_is_bind_get(PointerRNA *ptr)
return (csmd->bind_coords != NULL);
}
+static int rna_SurfaceDeformModifier_is_bound_get(PointerRNA *ptr)
+{
+ return (((SurfaceDeformModifierData *)ptr->data)->verts != NULL);
+}
+
static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
#ifdef WITH_ALEMBIC
@@ -1517,6 +1526,20 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mirror V", "Mirror the V texture coordinate around the 0.5 point");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "mirror_offset_u", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_offset[0]");
+ RNA_def_property_range(prop, -1, 1);
+ RNA_def_property_ui_range(prop, -1, 1, 2, 4);
+ RNA_def_property_ui_text(prop, "U Offset", "Amount to offset mirrored UVs from the 0.5 point on the U axis");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "mirror_offset_v", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "uv_offset[1]");
+ RNA_def_property_range(prop, -1, 1);
+ RNA_def_property_ui_range(prop, -1, 1, 2, 4);
+ RNA_def_property_ui_text(prop, "V Offset", "Amount to offset mirrored UVs from the 0.5 point on the V axis");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "tolerance");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -4702,6 +4725,33 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
+static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "SurfaceDeformModifier", "Modifier");
+ RNA_def_struct_ui_text(srna, "SurfaceDeform Modifier", "");
+ RNA_def_struct_sdna(srna, "SurfaceDeformModifierData");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+
+ prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Target", "Mesh object to deform with");
+ RNA_def_property_pointer_funcs(prop, NULL, "rna_SurfaceDeformModifier_target_set", NULL, "rna_Mesh_object_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_range(prop, 2.0f, 16.0f);
+ RNA_def_property_ui_text(prop, "Interpolation falloff", "Controls how much nearby polygons influence deformation");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_SurfaceDeformModifier_is_bound_get", NULL);
+ RNA_def_property_ui_text(prop, "Bound", "Whether geometry has been bound to target mesh");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+}
+
void RNA_def_modifier(BlenderRNA *brna)
{
StructRNA *srna;
@@ -4819,6 +4869,7 @@ void RNA_def_modifier(BlenderRNA *brna)
rna_def_modifier_datatransfer(brna);
rna_def_modifier_normaledit(brna);
rna_def_modifier_meshseqcache(brna);
+ rna_def_modifier_surfacedeform(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index b35142f2a58..8d42d746e1c 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -3327,6 +3327,7 @@ static void def_frame(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
RNA_def_struct_sdna_from(srna, "NodeFrame", "storage");
+ RNA_def_struct_translation_context(srna, BLT_I18NCONTEXT_ID_NODETREE);
prop = RNA_def_property(srna, "shrink", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_FRAME_SHRINK);
@@ -5721,8 +5722,8 @@ static void def_cmp_glare(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "streaks", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "angle");
- RNA_def_property_range(prop, 2, 16);
+ RNA_def_property_int_sdna(prop, NULL, "streaks");
+ RNA_def_property_range(prop, 1, 16);
RNA_def_property_ui_text(prop, "Streaks", "Total number of streaks");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -5739,7 +5740,7 @@ static void def_cmp_glare(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
prop = RNA_def_property(srna, "use_rotate_45", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "angle", 0);
+ RNA_def_property_boolean_sdna(prop, NULL, "star_45", 0);
RNA_def_property_ui_text(prop, "Rotate 45", "Simple star filter: add 45 degree rotation offset");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index f8b3bdd62e9..ecb011991e5 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -1312,8 +1312,12 @@ static void rna_Object_active_constraint_set(PointerRNA *ptr, PointerRNA value)
static bConstraint *rna_Object_constraints_new(Object *object, int type)
{
+ bConstraint *new_con = BKE_constraint_add_for_object(object, NULL, type);
+
+ ED_object_constraint_tag_update(object, new_con);
WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, object);
- return BKE_constraint_add_for_object(object, NULL, type);
+
+ return new_con;
}
static void rna_Object_constraints_remove(Object *object, ReportList *reports, PointerRNA *con_ptr)
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index c93f72e798f..0390ba04223 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -135,6 +135,19 @@ static int rna_Object_select_get(Object *ob, bContext *C, ReportList *reports)
return ((base->flag & BASE_SELECTED) != 0) ? 1 : 0;
}
+static int rna_Object_visible_get(Object *ob, bContext *C, ReportList *reports)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+
+ if (!base) {
+ BKE_reportf(reports, RPT_ERROR, "Object '%s' not in Render Layer '%s'!", ob->id.name + 2, sl->name);
+ return -1;
+ }
+
+ return ((base->flag & BASE_VISIBLED) != 0) ? 1 : 0;
+}
+
/* Convert a given matrix from a space to another (using the object and/or a bone as reference). */
static void rna_Scene_mat_convert_space(Object *ob, ReportList *reports, bPoseChannel *pchan,
float *mat, float *mat_ret, int from, int to)
@@ -569,6 +582,12 @@ void RNA_api_object(StructRNA *srna)
parm = RNA_def_boolean(func, "result", 0, "", "Object selected");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "visible_get", "rna_Object_visible_get");
+ RNA_def_function_ui_description(func, "Get the object visibility for the active render layer");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT | FUNC_USE_REPORTS);
+ parm = RNA_def_boolean(func, "result", 0, "", "Object visible");
+ RNA_def_function_return(func, parm);
+
/* Matrix space conversion */
func = RNA_def_function(srna, "convert_space", "rna_Scene_mat_convert_space");
RNA_def_function_ui_description(func, "Convert (transform) the given matrix from one space to another");
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 5fd4762e5be..ca0b4063616 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -1275,7 +1275,7 @@ static void rna_def_field(BlenderRNA *brna)
prop = RNA_def_property(srna, "falloff_power", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "f_power");
RNA_def_property_range(prop, 0.0f, 10.0f);
- RNA_def_property_ui_text(prop, "Falloff Power", "Falloff power (real gravitational falloff = 2)");
+ RNA_def_property_ui_text(prop, "Falloff Power", "");
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
prop = RNA_def_property(srna, "distance_min", PROP_FLOAT, PROP_NONE);
@@ -1394,6 +1394,11 @@ static void rna_def_field(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_SMOKE_DENSITY);
RNA_def_property_ui_text(prop, "Apply Density", "Adjust force strength based on smoke density");
RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+ prop = RNA_def_property(srna, "use_gravity_falloff", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", PFIELD_GRAVITATION);
+ RNA_def_property_ui_text(prop, "Gravity Falloff", "Multiply force by 1/distance²");
+ RNA_def_property_update(prop, 0, "rna_FieldSettings_update");
+
/* Pointer */
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index 28ce63a61bd..8d161466d56 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -524,12 +524,15 @@ static void rna_PoseChannel_active_constraint_set(PointerRNA *ptr, PointerRNA va
BKE_constraints_active_set(&pchan->constraints, (bConstraint *)value.data);
}
-static bConstraint *rna_PoseChannel_constraints_new(bPoseChannel *pchan, int type)
+static bConstraint *rna_PoseChannel_constraints_new(ID *id, bPoseChannel *pchan, Main *main, int type)
{
- /*WM_main_add_notifier(NC_OBJECT|ND_CONSTRAINT|NA_ADDED, object); */
- /* TODO, pass object also */
- /* TODO, new pose bones don't have updated draw flags */
- return BKE_constraint_add_for_pose(NULL, pchan, NULL, type);
+ Object *ob = (Object *)id;
+ bConstraint *new_con = BKE_constraint_add_for_pose(ob, pchan, NULL, type);
+
+ ED_object_constraint_dependency_tag_update(main, ob, new_con);
+ WM_main_add_notifier(NC_OBJECT | ND_CONSTRAINT | NA_ADDED, id);
+
+ return new_con;
}
static void rna_PoseChannel_constraints_remove(ID *id, bPoseChannel *pchan, ReportList *reports, PointerRNA *con_ptr)
@@ -764,6 +767,7 @@ static void rna_def_pose_channel_constraints(BlenderRNA *brna, PropertyRNA *cpro
/* Constraint collection */
func = RNA_def_function(srna, "new", "rna_PoseChannel_constraints_new");
RNA_def_function_ui_description(func, "Add a constraint to this object");
+ RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_SELF_ID); /* ID and Main needed for refresh */
/* return type */
parm = RNA_def_pointer(func, "constraint", "Constraint", "", "New constraint");
RNA_def_function_return(func, parm);
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 5f796261c73..36de2b85619 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -261,19 +261,18 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
-static void engine_collection_settings_create(RenderEngine *engine, struct CollectionEngineSettings *ces)
+static void engine_collection_settings_create(RenderEngine *engine, struct IDProperty *props)
{
extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
- PointerRNA ptr,cesptr;
+ PointerRNA ptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
- RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &cesptr);
func = &rna_RenderEngine_collection_settings_create_func;
RNA_parameter_list_create(&list, &ptr, func);
- RNA_parameter_set_lookup(&list, "collection_settings", &cesptr);
+ RNA_parameter_set_lookup(&list, "props", &props);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
@@ -512,7 +511,7 @@ static void rna_def_render_engine(BlenderRNA *brna)
func = RNA_def_function(srna, "collection_settings_create", NULL);
RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
- parm = RNA_def_pointer(func, "collection_settings", "CollectionEngineSettings", "", "");
+ parm = RNA_def_pointer(func, "collection_settings", "LayerCollectionSettings", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
/* tag for redraw */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 2fb1fa9c8d6..29bc5baab69 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -418,7 +418,7 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
/* interpolation */
{0, "", 0, N_("Interpolation"), "Standard transitions between keyframes"},
{GP_IPO_LINEAR, "LINEAR", ICON_IPO_LINEAR, "Linear", "Straight-line interpolation between A and B (i.e. no ease in/out)"},
- {GP_IPO_CURVEMAP, "CUSTOM", ICON_IPO_BEZIER, "Custom", "Custom interpolation defined using a curvemap"},
+ {GP_IPO_CURVEMAP, "CUSTOM", ICON_IPO_BEZIER, "Custom", "Custom interpolation defined using a curve map"},
/* easing */
{0, "", 0, N_("Easing (by strength)"), "Predefined inertial transitions, useful for motion graphics (from least to most ''dramatic'')"},
@@ -438,6 +438,12 @@ EnumPropertyItem rna_enum_gpencil_interpolation_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem rna_enum_layer_collection_mode_settings_type_items[] = {
+ {COLLECTION_MODE_OBJECT, "OBJECT", 0, "Object", ""},
+ {COLLECTION_MODE_EDIT, "EDIT", 0, "Edit", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
@@ -801,6 +807,21 @@ static void rna_Scene_frame_current_set(PointerRNA *ptr, int value)
data->r.cfra = value;
}
+static float rna_Scene_frame_float_get(PointerRNA *ptr)
+{
+ Scene *data = (Scene *)ptr->data;
+ return (float)data->r.cfra + data->r.subframe;
+}
+
+static void rna_Scene_frame_float_set(PointerRNA *ptr, float value)
+{
+ Scene *data = (Scene *)ptr->data;
+ /* if negative frames aren't allowed, then we can't use them */
+ FRAMENUMBER_MIN_CLAMP(value);
+ data->r.cfra = (int)value;
+ data->r.subframe = value - data->r.cfra;
+}
+
static float rna_Scene_frame_current_final_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
@@ -881,6 +902,12 @@ static void rna_Scene_preview_range_end_frame_set(PointerRNA *ptr, int value)
data->r.pefra = value;
}
+static void rna_Scene_show_subframe_update(Main *UNUSED(bmain), Scene *UNUSED(current_scene), PointerRNA *ptr)
+{
+ Scene *scene = (Scene *)ptr->id.data;
+ scene->r.subframe = 0.0f;
+}
+
static void rna_Scene_frame_update(Main *bmain, Scene *UNUSED(current_scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->id.data;
@@ -1876,41 +1903,30 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value)
gm->exitkey = value;
}
-static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr)
+static StructRNA *rna_LayerCollectionSettings_refine(PointerRNA *ptr)
{
-#ifdef WITH_CLAY_ENGINE
- RenderEngineSettings *res = (RenderEngineSettings *)ptr->data;
+ IDProperty *props = (IDProperty *)ptr->data;
+ BLI_assert(props && props->type == IDP_GROUP);
- if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
- return &RNA_RenderEngineSettingsClay;
- }
+ switch (props->subtype) {
+ case IDP_GROUP_SUB_ENGINE_RENDER:
+#ifdef WITH_CLAY_ENGINE
+ if (STREQ(props->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_LayerCollectionEngineSettingsClay;
+ }
#endif
- return &RNA_RenderEngineSettings;
-}
-
-static PointerRNA rna_RenderEngineSettings_active_get(PointerRNA *ptr)
-{
- Scene *scene = (Scene *)ptr->data;
- RenderEngineSettings *res;
-
- /* Ensure settings exists */
- DRW_render_settings_get(scene, scene->r.engine);
-
- res = BLI_findstring(&scene->engines_settings, scene->r.engine, offsetof(RenderEngineSettings, name));
-
- return rna_pointer_inherit_refine(ptr, &RNA_RenderEngineSettings, res);
-}
-
-static void rna_RenderEngineSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
-{
- Scene *sce = (Scene *)ptr->id.data;
- MaterialEngineSettingsClay *res;
-
- res = (MaterialEngineSettingsClay *)DRW_render_settings_get(sce, sce->r.engine);
-
- res->flag = CLAY_OUTDATED;
+ break;
+ case IDP_GROUP_SUB_MODE_OBJECT:
+ return &RNA_LayerCollectionModeSettingsObject;
+ break;
+ case IDP_GROUP_SUB_MODE_EDIT:
+ return &RNA_LayerCollectionModeSettingsEdit;
+ break;
+ default:
+ break;
+ }
- WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ return &RNA_LayerCollectionSettings;
}
static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame)
@@ -1968,9 +1984,10 @@ static KeyingSet *rna_Scene_keying_set_new(Scene *sce, ReportList *reports, cons
}
}
-static void rna_UnifiedPaintSettings_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_UnifiedPaintSettings_update(Main *UNUSED(bmain), bContext *C, Scene *scene, PointerRNA *UNUSED(ptr))
{
- Brush *br = BKE_paint_brush(BKE_paint_get_active(scene));
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Brush *br = BKE_paint_brush(BKE_paint_get_active(scene, sl));
WM_main_add_notifier(NC_BRUSH | NA_EDITED, br);
}
@@ -1993,11 +2010,11 @@ static void rna_UnifiedPaintSettings_unprojected_radius_set(PointerRNA *ptr, flo
ups->unprojected_radius = value;
}
-static void rna_UnifiedPaintSettings_radius_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_UnifiedPaintSettings_radius_update(Main *bmain, bContext *C, Scene *scene, PointerRNA *ptr)
{
/* changing the unified size should invalidate the overlay but also update the brush */
BKE_paint_invalidate_overlay_all();
- rna_UnifiedPaintSettings_update(bmain, scene, ptr);
+ rna_UnifiedPaintSettings_update(bmain, C, scene, ptr);
}
static char *rna_UnifiedPaintSettings_path(PointerRNA *UNUSED(ptr))
@@ -2235,10 +2252,7 @@ static void rna_SceneCollection_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
SceneCollection *sc = (SceneCollection *)ptr->data;
- SceneCollection *sc_master = BKE_collection_master(scene);
-
- BLI_strncpy_utf8(sc->name, value, sizeof(sc->name));
- BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+ BKE_collection_rename(scene, sc, value);
}
static void rna_SceneCollection_filter_set(PointerRNA *ptr, const char *value)
@@ -2259,19 +2273,62 @@ static PointerRNA rna_SceneCollection_objects_get(CollectionPropertyIterator *it
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((LinkData *)internal->link)->data);
}
-static SceneCollection *rna_SceneCollection_new(ID *id, SceneCollection *sc_parent, const char *name)
+static int rna_SceneCollection_move_above(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_collection_move_above(scene, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_SceneCollection_move_below(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_collection_move_below(scene, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main *bmain, SceneCollection *sc_dst)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_collection_move_into(scene, sc_dst, sc_src)) {
+ return 0;
+ }
+
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static SceneCollection *rna_SceneCollection_new(
+ ID *id, SceneCollection *sc_parent, Main *bmain, const char *name)
{
Scene *scene = (Scene *)id;
SceneCollection *sc = BKE_collection_add(scene, sc_parent, name);
- DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return sc;
}
static void rna_SceneCollection_remove(
- ID *id, SceneCollection *sc_parent, ReportList *reports, PointerRNA *sc_ptr)
+ ID *id, SceneCollection *sc_parent, Main *bmain, ReportList *reports, PointerRNA *sc_ptr)
{
Scene *scene = (Scene *)id;
SceneCollection *sc = sc_ptr->data;
@@ -2291,7 +2348,7 @@ static void rna_SceneCollection_remove(
RNA_POINTER_INVALIDATE(sc_ptr);
- DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -2329,6 +2386,10 @@ void rna_SceneCollection_object_link(
/* TODO(sergey): Only update relations for the current scene. */
DAG_relations_tag_update(bmain);
+
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
+
DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
@@ -2354,82 +2415,94 @@ static void rna_SceneCollection_object_unlink(
/****** layer collection engine settings *******/
-static StructRNA *rna_CollectionEngineSettings_refine(struct PointerRNA *ptr)
-{
- CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;
+#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _ENGINE_, _MODE_, _NAME_) \
+static _TYPE_ rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_get(PointerRNA *ptr) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ return BKE_collection_engine_property_value_get_##_TYPE_(props, #_NAME_); \
+} \
+ \
+static void rna_LayerEngineSettings_##_ENGINE_##_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \
+{ \
+ IDProperty *props = (IDProperty *)ptr->data; \
+ BKE_collection_engine_property_value_set_##_TYPE_(props, #_NAME_, value); \
+} \
- if (STREQ(ces->name, "BLENDER_CLAY")) {
- return &RNA_CollectionEngineSettingsClay;
- }
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, Clay, COLLECTION_MODE_NONE, _NAME_)
- /* TODO - handle other engines */
- TODO_LAYER;
- (void) ces;
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, Clay, COLLECTION_MODE_NONE, _NAME_)
- return &RNA_CollectionEngineSettings;
-}
+#define RNA_LAYER_ENGINE_CLAY_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, Clay, COLLECTION_MODE_NONE, _NAME_)
-/****** clay engine settings *******/
+/* mode engines */
-#define RNA_LAYER_ENGINE_USE_GET_SET(_NAME_) \
- static int rna_LayerEngineSettings_##_NAME_##_use_get(PointerRNA *ptr) \
- { \
- CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
- return BKE_collection_engine_property_use_get(ces, #_NAME_) ? 1 : 0; \
- } \
- \
- static void rna_LayerEngineSettings_##_NAME_##_use_set(PointerRNA *ptr, int value) \
- { \
- CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
- BKE_collection_engine_property_use_set(ces, #_NAME_, value? true : false); \
- }
+#define RNA_LAYER_MODE_OBJECT_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
-#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _NAME_) \
-static _TYPE_ rna_LayerEngineSettings_##_NAME_##_get(PointerRNA *ptr) \
-{ \
- CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
- return BKE_collection_engine_property_value_get_##_TYPE_(ces, #_NAME_); \
-} \
- \
-static void rna_LayerEngineSettings_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \
-{ \
- CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
- BKE_collection_engine_property_value_set_##_TYPE_(ces, #_NAME_, value); \
-} \
- RNA_LAYER_ENGINE_USE_GET_SET(_NAME_)
+#define RNA_LAYER_MODE_OBJECT_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
+
+#define RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, ObjectMode, COLLECTION_MODE_OBJECT, _NAME_)
+
+#define RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(float, EditMode, COLLECTION_MODE_EDIT, _NAME_)
+
+#define RNA_LAYER_MODE_EDIT_GET_SET_INT(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(int, EditMode, COLLECTION_MODE_EDIT, _NAME_)
-#define RNA_LAYER_ENGINE_GET_SET_FLOAT(_NAME_) \
- RNA_LAYER_ENGINE_GET_SET(float, _NAME_)
+#define RNA_LAYER_MODE_EDIT_GET_SET_BOOL(_NAME_) \
+ RNA_LAYER_ENGINE_GET_SET(bool, EditMode, COLLECTION_MODE_EDIT, _NAME_)
-#define RNA_LAYER_ENGINE_GET_SET_INT(_NAME_) \
- RNA_LAYER_ENGINE_GET_SET(int, _NAME_)
+/* clay engine */
+RNA_LAYER_ENGINE_CLAY_GET_SET_INT(matcap_icon)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_rotation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_hue)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_saturation)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(matcap_value)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_cavity)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_factor_edge)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_distance)
+RNA_LAYER_ENGINE_CLAY_GET_SET_FLOAT(ssao_attenuation)
+/* object engine */
+RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire)
+RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_backface_culling)
-RNA_LAYER_ENGINE_GET_SET_INT(type)
-RNA_LAYER_ENGINE_GET_SET_INT(matcap_icon)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_rotation)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_hue)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_saturation)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_value)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_cavity)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_edge)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_distance)
-RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_attenuation)
+/* mesh engine */
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(show_occlude_wire)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(face_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(vert_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_BOOL(loop_normals_show)
+RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(normals_length)
+RNA_LAYER_MODE_EDIT_GET_SET_FLOAT(backwire_opacity)
-#undef RNA_LAYER_ENGINE_GET_SET_INT
-#undef RNA_LAYER_ENGINE_GET_SET_FLOAT
#undef RNA_LAYER_ENGINE_GET_SET
-#undef RNA_LAYER_ENGINE_USE_GET_SET
-static void rna_CollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
+static void rna_LayerCollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
{
- SceneLayer *sl = CTX_data_scene_layer(C);
- LayerCollection *lc = CTX_data_layer_collection(C);
- BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+ Scene *scene = CTX_data_scene(C);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
}
/***********************************/
+static void rna_LayerCollectionSettings_name_get(PointerRNA *ptr, char *value)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ strcpy(value, props->name);
+}
+
+static int rna_LayerCollectionSettings_name_length(PointerRNA *ptr)
+{
+ IDProperty *props = (IDProperty *)ptr->data;
+ return strnlen(props->name, sizeof(props->name));
+}
+
static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value)
{
SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
@@ -2446,10 +2519,7 @@ static void rna_LayerCollection_name_set(PointerRNA *ptr, const char *value)
{
Scene *scene = (Scene *)ptr->id.data;
SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
- SceneCollection *sc_master = BKE_collection_master(scene);
-
- BLI_strncpy_utf8(sc->name, value, sizeof(sc->name));
- BLI_uniquename(&sc_master->scene_collections, sc, DATA_("SceneCollection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+ BKE_collection_rename(scene, sc, value);
}
static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *iter)
@@ -2459,34 +2529,55 @@ static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *it
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
}
-static PointerRNA rna_LayerCollection_engine_settings_get(ID *UNUSED(id), LayerCollection *lc, bContext *C, const char *engine)
+static int rna_LayerCollection_move_above(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
{
- Scene *scene = CTX_data_scene(C);
- const char *engine_name;
+ Scene *scene = (Scene *)id;
- if (STREQ(engine, NO_ENGINE)) {
- RenderData *rd = &scene->r;
- engine_name = rd->engine;
+ if (!BKE_layer_collection_move_above(scene, lc_dst, lc_src)) {
+ return 0;
}
- else {
- engine_name = engine;
+
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_LayerCollection_move_below(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_layer_collection_move_below(scene, lc_dst, lc_src)) {
+ return 0;
+ }
+
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
+}
+
+static int rna_LayerCollection_move_into(ID *id, LayerCollection *lc_src, Main *bmain, LayerCollection *lc_dst)
+{
+ Scene *scene = (Scene *)id;
+
+ if (!BKE_layer_collection_move_into(scene, lc_dst, lc_src)) {
+ return 0;
}
- PointerRNA ptr;
- CollectionEngineSettings *ces = BKE_layer_collection_engine_get(lc, engine_name);
- RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &ptr);
- return rna_pointer_inherit_refine(&ptr, &RNA_CollectionEngineSettings, ces);
+ DAG_relations_tag_update(bmain);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return 1;
}
-static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr)
+static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *UNUSED(ptr))
{
Scene *scene = CTX_data_scene(C);
- LayerCollection *lc = ptr->data;
- SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
/* hide and deselect bases that are directly influenced by this LayerCollection */
- BKE_scene_layer_base_flag_recalculate(sl);
- BKE_scene_layer_engine_settings_collection_recalculate(sl, lc);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
}
@@ -2496,10 +2587,10 @@ static void rna_LayerCollection_hide_select_update(bContext *C, PointerRNA *ptr)
if ((lc->flag & COLLECTION_SELECTABLE) == 0) {
Scene *scene = CTX_data_scene(C);
- SceneLayer *sl = BKE_scene_layer_find_from_collection(scene, lc);
/* deselect bases that are directly influenced by this LayerCollection */
- BKE_scene_layer_base_flag_recalculate(sl);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(&scene->id, 0);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, CTX_data_scene(C));
}
}
@@ -2546,8 +2637,9 @@ LayerCollection * rna_SceneLayer_collection_link(
Scene *scene = (Scene *)id;
LayerCollection *lc = BKE_collection_link(sl, sc);
- /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */
DAG_relations_tag_update(bmain);
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_LAYER, scene);
return lc;
@@ -2565,10 +2657,9 @@ static void rna_SceneLayer_collection_unlink(
BKE_collection_unlink(sl, lc);
- /* needed otherwise the depgraph will contain freed objects which can crash, see [#20958] */
- /* TODO(sergey/dfelinto): Only update relations for the current scenelayer. */
DAG_relations_tag_update(bmain);
-
+ /* TODO(sergey): Use proper flag for tagging here. */
+ DAG_id_tag_update(id, 0);
WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
}
@@ -2729,12 +2820,14 @@ static void rna_SceneLayer_active_layer_set(PointerRNA *ptr, PointerRNA value)
if (index != -1) scene->active_layer = index;
}
-static SceneLayer *rna_SceneLayer_new(ID *id, Scene *UNUSED(sce), const char *name)
+static SceneLayer *rna_SceneLayer_new(
+ ID *id, Scene *UNUSED(sce), Main *bmain, const char *name)
{
Scene *scene = (Scene *)id;
SceneLayer *sl = BKE_scene_layer_add(scene, name);
DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return sl;
@@ -2755,6 +2848,7 @@ static void rna_SceneLayer_remove(
RNA_POINTER_INVALIDATE(sl_ptr);
DAG_id_tag_update(&scene->id, 0);
+ DAG_relations_tag_update(bmain);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -2764,7 +2858,6 @@ static void rna_ObjectBase_select_update(Main *UNUSED(bmain), Scene *UNUSED(scen
short mode = (base->flag & BASE_SELECTED) ? BA_SELECT : BA_DESELECT;
ED_object_base_select(base, mode);
}
-
#else
/* Grease Pencil Interpolation tool settings */
@@ -3607,6 +3700,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
* from the active brush */
prop = RNA_def_property(srna, "size", PROP_INT, PROP_PIXEL);
RNA_def_property_int_funcs(prop, NULL, "rna_UnifiedPaintSettings_size_set", NULL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS * 10);
RNA_def_property_ui_range(prop, 1, MAX_BRUSH_PIXEL_RADIUS, 1, -1);
RNA_def_property_ui_text(prop, "Radius", "Radius of the brush");
@@ -3614,6 +3708,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "unprojected_radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_funcs(prop, NULL, "rna_UnifiedPaintSettings_unprojected_radius_set", NULL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.001, FLT_MAX);
RNA_def_property_ui_range(prop, 0.001, 1, 0, -1);
RNA_def_property_ui_text(prop, "Unprojected Radius", "Radius of brush in Blender units");
@@ -3621,6 +3716,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "alpha");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
@@ -3629,6 +3725,7 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "weight", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "weight");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
@@ -3636,12 +3733,14 @@ static void rna_def_unified_paint_settings(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "rgb");
RNA_def_property_ui_text(prop, "Color", "");
RNA_def_property_update(prop, 0, "rna_UnifiedPaintSettings_update");
prop = RNA_def_property(srna, "secondary_color", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_float_sdna(prop, NULL, "secondary_rgb");
RNA_def_property_ui_text(prop, "Secondary Color", "");
@@ -5641,7 +5740,7 @@ static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_SceneCollection_new");
RNA_def_function_ui_description(func, "Add a collection to scene");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
parm = RNA_def_string(func, "name", "SceneCollection", 0, "", "New name for the collection (not unique)");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection");
@@ -5649,7 +5748,7 @@ static void rna_def_scene_collections(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "remove", "rna_SceneCollection_remove");
RNA_def_function_ui_description(func, "Remove a collection layer");
- RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "layer", "SceneCollection", "", "Collection to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
@@ -5692,6 +5791,9 @@ static void rna_def_scene_collection(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
srna = RNA_def_struct(brna, "SceneCollection", NULL);
RNA_def_struct_ui_text(srna, "Scene Collection", "Collection");
@@ -5724,6 +5826,28 @@ static void rna_def_scene_collection(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, "rna_SceneCollection_objects_get", NULL, NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Filter Objects", "All the objects dynamically added to this collection via the filter");
+
+ /* Functions */
+ func = RNA_def_function(srna, "move_above", "rna_SceneCollection_move_above");
+ RNA_def_function_ui_description(func, "Move collection after another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection above which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_below", "rna_SceneCollection_move_below");
+ RNA_def_function_ui_description(func, "Move collection before another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Reference collection below which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_into", "rna_SceneCollection_move_into");
+ RNA_def_function_ui_description(func, "Move collection into another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Collection to insert into");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
}
static void rna_def_layer_collection_override(BlenderRNA *brna)
@@ -5741,14 +5865,7 @@ static void rna_def_layer_collection_override(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
-#define RNA_LAYER_ENGINE_USE(_NAME_) \
- prop = RNA_def_property(srna, #_NAME_"_use", PROP_BOOLEAN, PROP_NONE); \
- RNA_def_property_boolean_funcs(prop, \
- "rna_LayerEngineSettings_"#_NAME_"_use_get", \
- "rna_LayerEngineSettings_"#_NAME_"_use_set"); \
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); \
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
-
+#ifdef WITH_CLAY_ENGINE
static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
{
StructRNA *srna;
@@ -5782,126 +5899,187 @@ static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem clay_matcap_type[] = {
- {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
- {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
- {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "CollectionEngineSettingsClay", NULL);
- RNA_def_struct_sdna(srna, "CollectionEngineSettings");
+ srna = RNA_def_struct(brna, "LayerCollectionEngineSettingsClay", NULL);
RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection");
- prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "Engine name");
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_struct_name_property(srna, prop);
+ RNA_define_verify_sdna(0); /* not in sdna */
/* see RNA_LAYER_ENGINE_GET_SET macro */
-
- prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_type_get", "rna_LayerEngineSettings_type_set", NULL);
- RNA_def_property_enum_items(prop, clay_matcap_type);
- RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
- RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(type)
-
prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_matcap_icon_get", "rna_LayerEngineSettings_matcap_icon_set", NULL);
+ RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_icon_get", "rna_LayerEngineSettings_Clay_matcap_icon_set", NULL);
RNA_def_property_enum_items(prop, clay_matcap_items);
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(matcap_icon)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_rotation_get", "rna_LayerEngineSettings_matcap_rotation_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_rotation_get", "rna_LayerEngineSettings_Clay_matcap_rotation_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(matcap_rotation)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_hue_get", "rna_LayerEngineSettings_matcap_hue_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_hue_get", "rna_LayerEngineSettings_Clay_matcap_hue_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(matcap_hue)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_saturation_get", "rna_LayerEngineSettings_matcap_saturation_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_saturation_get", "rna_LayerEngineSettings_Clay_matcap_saturation_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(matcap_saturation)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_value_get", "rna_LayerEngineSettings_matcap_value_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_matcap_value_get", "rna_LayerEngineSettings_Clay_matcap_value_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(matcap_value)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_cavity_get", "rna_LayerEngineSettings_ssao_factor_cavity_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_factor_cavity_get", "rna_LayerEngineSettings_Clay_ssao_factor_cavity_set", NULL);
RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(ssao_factor_cavity)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_edge_get", "rna_LayerEngineSettings_ssao_factor_edge_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_factor_edge_get", "rna_LayerEngineSettings_Clay_ssao_factor_edge_set", NULL);
RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(ssao_factor_edge)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_distance_get", "rna_LayerEngineSettings_ssao_distance_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_distance_get", "rna_LayerEngineSettings_Clay_ssao_distance_set", NULL);
RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
RNA_def_property_range(prop, 0.0f, 100000.0f);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(ssao_distance)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_attenuation_get", "rna_LayerEngineSettings_ssao_attenuation_set", NULL);
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Clay_ssao_attenuation_get", "rna_LayerEngineSettings_Clay_ssao_attenuation_set", NULL);
RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
RNA_def_property_range(prop, 1.0f, 100000.0f);
RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
- RNA_LAYER_ENGINE_USE(ssao_attenuation)
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
}
+#endif /* WITH_CLAY_ENGINE */
-static void rna_def_layer_collection_engine_settings(BlenderRNA *brna)
+static void rna_def_layer_collection_mode_settings_object(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "CollectionEngineSettings", NULL);
- RNA_def_struct_ui_text(srna, "Collections Engine Settings", "Engine specific settings for this collection");
- RNA_def_struct_refine_func(srna, "rna_CollectionEngineSettings_refine");
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsObject", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Object Mode Settings", "Object Mode specific settings for this collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "show_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Wire", "Add the object's wireframe over solid drawing");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_ObjectMode_show_wire_get", "rna_LayerEngineSettings_ObjectMode_show_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "show_backface_culling", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Backface Culling", "");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_ObjectMode_show_backface_culling_get", "rna_LayerEngineSettings_ObjectMode_show_backface_culling_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_layer_collection_mode_settings_edit(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionModeSettingsEdit", "LayerCollectionSettings");
+ RNA_def_struct_ui_text(srna, "Collections Edit Mode Settings", "Edit Mode specific settings to be overridden per collection");
+ RNA_define_verify_sdna(0); /* not in sdna */
+
+ /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+ prop = RNA_def_property(srna, "show_occlude_wire", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Hidden Wire", "Use hidden wireframe display");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_show_occlude_wire_get", "rna_LayerEngineSettings_EditMode_show_occlude_wire_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "face_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Normals", "Display face normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_face_normals_show_get", "rna_LayerEngineSettings_EditMode_face_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "vert_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Vertex Normals", "Display vertex normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_vert_normals_show_get", "rna_LayerEngineSettings_EditMode_vert_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "loop_normals_show", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Draw Split Normals", "Display vertex-per-face normals as lines");
+ RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_EditMode_loop_normals_show_get", "rna_LayerEngineSettings_EditMode_loop_normals_show_set");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "normals_length", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "Normal Size", "Display size for normals in the 3D view");
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_normals_length_get", "rna_LayerEngineSettings_EditMode_normals_length_set", NULL);
+ RNA_def_property_range(prop, 0.00001, 1000.0);
+ RNA_def_property_ui_range(prop, 0.01, 10.0, 10.0, 2);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ prop = RNA_def_property(srna, "backwire_opacity", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "Backwire Opacity", "Opacity when rendering transparent wires");
+ RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_EditMode_backwire_opacity_get", "rna_LayerEngineSettings_EditMode_backwire_opacity_set", NULL);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollectionEngineSettings_update");
+
+ RNA_define_verify_sdna(1); /* not in sdna */
+}
+
+static void rna_def_layer_collection_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "LayerCollectionSettings", NULL);
+ RNA_def_struct_ui_text(srna, "Layer Collection Settings",
+ "Engine specific settings that can be overriden by LayerCollection");
+ RNA_def_struct_refine_func(srna, "rna_LayerCollectionSettings_refine");
+
+ RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
- RNA_def_property_ui_text(prop, "Name", "Engine name");
+ RNA_def_property_string_funcs(prop, "rna_LayerCollectionSettings_name_get", "rna_LayerCollectionSettings_name_length", NULL);
+ RNA_def_property_ui_text(prop, "Name", "Engine Name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
- /* the engine specific structs */
+#ifdef WITH_CLAY_ENGINE
rna_def_layer_collection_engine_settings_clay(brna);
-}
+#endif
-#undef RNA_LAYER_ENGINE_USE
+ rna_def_layer_collection_mode_settings_object(brna);
+ rna_def_layer_collection_mode_settings_edit(brna);
+
+ RNA_define_verify_sdna(1);
+}
static void rna_def_layer_collection(BlenderRNA *brna)
{
@@ -5942,13 +6120,32 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "LayerCollectionOverride");
RNA_def_property_ui_text(prop, "Collection Overrides", "");
- func = RNA_def_function(srna, "get_engine_settings", "rna_LayerCollection_engine_settings_get");
- RNA_def_function_ui_description(func, "Return the engine settings for this collection");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
- parm = RNA_def_string(func, "engine", NO_ENGINE, MAX_NAME, "Engine", "use context one by default");
- RNA_def_parameter_clear_flags(parm, 0, PARM_REQUIRED);
- parm = RNA_def_pointer(func, "result", "CollectionEngineSettings", "", "");
- RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+ /* Override settings */
+ prop = RNA_def_property(srna, "engine_overrides", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_ui_text(prop, "Collection Settings", "Override of engine specific render settings");
+
+ /* Functions */
+ func = RNA_def_function(srna, "move_above", "rna_LayerCollection_move_above");
+ RNA_def_function_ui_description(func, "Move collection after another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection above which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_below", "rna_LayerCollection_move_below");
+ RNA_def_function_ui_description(func, "Move collection before another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Reference collection below which the collection will move");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "move_into", "rna_LayerCollection_move_into");
+ RNA_def_function_ui_description(func, "Move collection into another");
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
+ parm = RNA_def_pointer(func, "lc_dst", "LayerCollection", "Collection", "Collection to insert into");
+ parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded");
RNA_def_function_return(func, parm);
/* Flags */
@@ -5966,12 +6163,6 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Hide Selectable", "Restrict selection");
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_LayerCollection_hide_select_update");
- prop = RNA_def_property(srna, "is_unfolded", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_FOLDED);
- RNA_def_property_ui_icon(prop, ICON_RIGHTARROW, 1);
- RNA_def_property_ui_text(prop, "Folded", "Folded collection");
- RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
-
/* TODO_LAYER_OVERRIDE */
}
@@ -6130,7 +6321,7 @@ static void rna_def_scene_layers(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "new", "rna_SceneLayer_new");
RNA_def_function_ui_description(func, "Add a render layer to scene");
- RNA_def_function_flag(func, FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
parm = RNA_def_string(func, "name", "SceneLayer", 0, "", "New name for the render layer (not unique)");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "result", "SceneLayer", "", "Newly created render layer");
@@ -6138,7 +6329,7 @@ static void rna_def_scene_layers(BlenderRNA *brna, PropertyRNA *cprop)
func = RNA_def_function(srna, "remove", "rna_SceneLayer_remove");
RNA_def_function_ui_description(func, "Remove a render layer");
- RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_REPORTS);
parm = RNA_def_pointer(func, "layer", "SceneLayer", "", "Render layer to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
@@ -6488,7 +6679,7 @@ static void rna_def_scene_image_format_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "jpeg2k_codec", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "jp2_codec");
RNA_def_property_enum_items(prop, jp2_codec_items);
- RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpek2000");
+ RNA_def_property_ui_text(prop, "Codec", "Codec settings for Jpeg2000");
RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL);
#endif
@@ -6894,113 +7085,25 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna)
#endif
#ifdef WITH_CLAY_ENGINE
-static void rna_def_render_engine_settings_clay(BlenderRNA *brna)
+static void UNUSED_FUNCTION(rna_def_scene_engine_settings_clay)(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- static EnumPropertyItem clay_matcap_items[] = {
- {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
- {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
- {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
- {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
- {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
- {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
- {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
- {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
- {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
- {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
- {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
- {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
- {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
- {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
- {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
- {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
- {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
- {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
- {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
- {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
- {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
- {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
- {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
- {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
- {0, NULL, 0, NULL, NULL}
- };
-
- srna = RNA_def_struct(brna, "RenderEngineSettingsClay", "RenderEngineSettings");
- RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
- RNA_def_struct_sdna_from(srna, "RenderEngineSettingsClay", "data");
-
- prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_items(prop, clay_matcap_items);
- RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
- RNA_def_property_float_sdna(prop, NULL, "matcap_val");
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
- RNA_def_property_range(prop, 0.0f, 250.0f);
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
- prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
- RNA_def_property_range(prop, 0.0f, 250.0f);
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+ srna = RNA_def_struct(brna, "SceneEngineSettingsClay", "SceneEngineSettings");
+ RNA_def_struct_ui_text(srna, "Clay Scene Settings", "Clay Engine settings");
- prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
- RNA_def_property_range(prop, 0.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
-
- prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
- RNA_def_property_range(prop, 1.0f, 100000.0f);
- RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
- RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+ RNA_define_verify_sdna(0); /* not in sdna */
/* Clay settings */
prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Samples", "Number of samples");
RNA_def_property_range(prop, 1, 500);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
-}
-#endif
-
-static void rna_def_scene_render_engine(BlenderRNA *brna)
-{
- StructRNA *srna;
- srna = RNA_def_struct(brna, "RenderEngineSettings", NULL);
- RNA_def_struct_ui_text(srna, "Render Engine Settings", "Engine specific render settings");
- RNA_def_struct_sdna(srna, "RenderEngineSettings");
- RNA_def_struct_refine_func(srna, "rna_RenderEngineSettings_refine");
-
-#ifdef WITH_CLAY_ENGINE
- rna_def_render_engine_settings_clay(brna);
-#endif
+ RNA_define_verify_sdna(1); /* not in sdna */
}
+#endif /* WITH_CLAY_ENGINE */
static void rna_def_scene_render_data(BlenderRNA *brna)
{
@@ -8309,8 +8412,19 @@ void RNA_def_scene(BlenderRNA *brna)
prop = RNA_def_property(srna, "frame_subframe", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "r.subframe");
RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
-
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 2);
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
+
+ prop = RNA_def_property(srna, "frame_float", PROP_FLOAT, PROP_TIME);
+ RNA_def_property_ui_text(prop, "Current Sub-Frame", "");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_range(prop, MINAFRAME, MAXFRAME);
+ RNA_def_property_ui_range(prop, MINAFRAME, MAXFRAME, 0.1, 2);
+ RNA_def_property_float_funcs(prop, "rna_Scene_frame_float_get", "rna_Scene_frame_float_set", NULL);
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_frame_update");
+
prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_int_sdna(prop, NULL, "r.sfra");
@@ -8375,7 +8489,15 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_int_funcs(prop, NULL, "rna_Scene_preview_range_end_frame_set", NULL);
RNA_def_property_ui_text(prop, "Preview Range End Frame", "Alternative end frame for UI playback");
RNA_def_property_update(prop, NC_SCENE | ND_FRAME, NULL);
-
+
+ /* Subframe for moblur debug. */
+ prop = RNA_def_property(srna, "show_subframe", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_boolean_sdna(prop, NULL, "r.flag", SCER_SHOW_SUBFRAME);
+ RNA_def_property_ui_text(prop, "Show Subframe",
+ "Show current scene subframe and allow set it using interface tools");
+ RNA_def_property_update(prop, NC_SCENE | ND_FRAME, "rna_Scene_show_subframe_update");
+
/* Timeline / Time Navigation settings */
prop = RNA_def_property(srna, "show_keys_from_selected_only", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SCE_KEYS_NO_SELONLY);
@@ -8499,14 +8621,11 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Render Data", "");
/* Render Engine Data */
- prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
- RNA_def_property_struct_type(prop, "RenderEngineSettings");
- RNA_def_property_ui_text(prop, "Render Engine Settings", "Engine specific render settings");
-
- prop = RNA_def_property(srna, "active_engine_settings", PROP_POINTER, PROP_NONE);
- RNA_def_property_struct_type(prop, "RenderEngineSettings");
- RNA_def_property_pointer_funcs(prop, "rna_RenderEngineSettings_active_get", NULL, NULL, NULL);
- RNA_def_property_ui_text(prop, "Active Render Engine Settings", "Active Engine specific render settings for this scene");
+ prop = RNA_def_property(srna, "collection_properties", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "collection_properties->data.group", NULL);
+ RNA_def_property_struct_type(prop, "LayerCollectionSettings");
+ RNA_def_property_ui_text(prop, "Collection Settings",
+ "Engine specific render settings to be overridden by collections");
/* Safe Areas */
prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
@@ -8654,13 +8773,12 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_scene_collection(brna);
rna_def_layer_collection(brna);
rna_def_layer_collection_override(brna);
- rna_def_layer_collection_engine_settings(brna);
rna_def_scene_layer(brna);
rna_def_object_base(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
+ rna_def_layer_collection_settings(brna);
rna_def_scene_render_data(brna);
- rna_def_scene_render_engine(brna);
rna_def_scene_render_layer(brna);
rna_def_gpu_fx(brna);
rna_def_scene_render_view(brna);
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index fe781a309a4..37d9c0747fd 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -243,9 +243,9 @@ static void rna_Scene_alembic_export(
.use_subdiv_schema = use_subdiv_schema,
.compression_type = compression_type,
.packuv = packuv,
- .triangulate = triangulate,
- .quad_method = quad_method,
- .ngon_method = ngon_method,
+ .triangulate = triangulate,
+ .quad_method = quad_method,
+ .ngon_method = ngon_method,
.global_scale = scale,
};
@@ -263,34 +263,59 @@ static void rna_Scene_alembic_export(
/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
#include "../../collada/collada.h"
+/* Note: This definition must match to the generated function call */
static void rna_Scene_collada_export(
Scene *scene,
- const char *filepath,
+ bContext *C,
+ const char *filepath,
int apply_modifiers,
- int export_mesh_type,
+ int export_mesh_type,
int selected,
int include_children,
int include_armatures,
int include_shapekeys,
int deform_bones_only,
-
int active_uv_only,
int include_uv_textures,
int include_material_textures,
int use_texture_copies,
-
- int use_ngons,
+ int triangulate,
int use_object_instantiation,
int use_blender_profile,
int sort_by_name,
+ int export_transformation_type,
int open_sim,
- int export_transformation_type)
+ int limit_precision,
+ int keep_bind_info)
{
- collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
- include_children, include_armatures, include_shapekeys, deform_bones_only,
- active_uv_only, include_uv_textures, include_material_textures,
- use_texture_copies, use_ngons, use_object_instantiation, use_blender_profile, sort_by_name, export_transformation_type, open_sim);
+ collada_export(scene,
+ CTX_data_scene_layer(C),
+ filepath,
+
+ apply_modifiers,
+ export_mesh_type,
+
+ selected,
+ include_children,
+ include_armatures,
+ include_shapekeys,
+ deform_bones_only,
+
+ active_uv_only,
+ include_uv_textures,
+ include_material_textures,
+ use_texture_copies,
+
+ triangulate,
+ use_object_instantiation,
+ use_blender_profile,
+ sort_by_name,
+
+ export_transformation_type,
+ open_sim,
+ limit_precision,
+ keep_bind_info);
}
#endif
@@ -354,30 +379,63 @@ void RNA_api_scene(StructRNA *srna)
parm = RNA_def_string(func, "filepath", NULL, FILE_MAX, "File Path", "File path to write Collada file");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
- RNA_def_boolean(func, "apply_modifiers", 0, "Apply Modifiers", "Apply modifiers");
+
+ RNA_def_boolean(func, "apply_modifiers", false,
+ "Apply Modifiers", "Apply modifiers to exported mesh (non destructive))");
+
RNA_def_int(func, "export_mesh_type", 0, INT_MIN, INT_MAX,
"Resolution", "Modifier resolution for export", INT_MIN, INT_MAX);
- RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
- RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)");
- RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)");
- RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
- RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures");
-
- RNA_def_boolean(func, "active_uv_only", 0, "Active UV Layer only", "Export only the active UV Layer");
- RNA_def_boolean(func, "include_uv_textures", 0, "Include UV Textures", "Export textures assigned to the object UV maps");
- RNA_def_boolean(func, "include_material_textures", 0, "Include Material Textures", "Export textures assigned to the object Materials");
- RNA_def_boolean(func, "use_texture_copies", 0, "copy", "Copy textures to same folder where the .dae file is exported");
-
- RNA_def_boolean(func, "use_ngons", 1, "Use NGons", "Keep NGons in Export");
- RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data");
- RNA_def_boolean(func, "use_blender_profile", 1, "Use Blender Profile", "Export additional Blender specific information (for material, shaders, bones, etc.)");
- RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name");
- RNA_def_boolean(func, "open_sim", 0, "Export for SL/OpenSim", "Compatibility mode for SL, OpenSim and similar online worlds");
+
+ RNA_def_boolean(func, "selected", false, "Selection Only", "Export only selected elements");
+
+ RNA_def_boolean(func, "include_children", false,
+ "Include Children", "Export all children of selected objects (even if not selected)");
+
+ RNA_def_boolean(func, "include_armatures", false,
+ "Include Armatures", "Export related armatures (even if not selected)");
+
+ RNA_def_boolean(func, "include_shapekeys", true, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
+
+ RNA_def_boolean(func, "deform_bones_only", false,
+ "Deform Bones only", "Only export deforming bones with armatures");
+
+ RNA_def_boolean(func, "active_uv_only", false, "Only Selected UV Map", "Export only the selected UV Map");
+
+ RNA_def_boolean(func, "include_uv_textures", false,
+ "Include UV Textures", "Export textures assigned to the object UV Maps");
+
+ RNA_def_boolean(func, "include_material_textures", false,
+ "Include Material Textures", "Export textures assigned to the object Materials");
+
+ RNA_def_boolean(func, "use_texture_copies", true,
+ "Copy", "Copy textures to same folder where the .dae file is exported");
+
+ RNA_def_boolean(func, "triangulate", true, "Triangulate", "Export Polygons (Quads & NGons) as Triangles");
+
+ RNA_def_boolean(func, "use_object_instantiation", true,
+ "Use Object Instances", "Instantiate multiple Objects from same Data");
+
+ RNA_def_boolean(func, "use_blender_profile", true, "Use Blender Profile",
+ "Export additional Blender specific information (for material, shaders, bones, etc.)");
+
+ RNA_def_boolean(func, "sort_by_name", false, "Sort by Object name", "Sort exported data by Object name");
RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX,
- "Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+ "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX);
+
+ RNA_def_boolean(func, "open_sim", false,
+ "Export to SL/OpenSim", "Compatibility mode for SL, OpenSim and other compatible online worlds");
+
+ RNA_def_boolean(func, "limit_precision", false,
+ "Limit Precision",
+ "Reduce the precision of the exported data to 6 digits");
+
+ RNA_def_boolean(func, "keep_bind_info", false,
+ "Keep Bind Info",
+ "Store bind pose information in custom bone properties for later use during Collada export");
+
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- RNA_def_function_ui_description(func, "Export to collada file");
#endif
#ifdef WITH_ALEMBIC
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 40aea37d9d2..26d85aee68a 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -148,10 +148,11 @@ static PointerRNA rna_ParticleBrush_curve_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_CurveMapping, NULL);
}
-static void rna_ParticleEdit_redo(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ParticleEdit_redo(Main *UNUSED(bmain), bContext *C, Scene *scene, PointerRNA *UNUSED(ptr))
{
- Object *ob = (scene->basact) ? scene->basact->object : NULL;
- PTCacheEdit *edit = PE_get_current(scene, ob);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
+ PTCacheEdit *edit = PE_get_current(scene, sl, ob);
if (!edit)
return;
@@ -211,14 +212,14 @@ static int rna_ParticleEdit_editable_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
- return (pset->object && pset->scene && PE_get_current(pset->scene, pset->object));
+ return (pset->object && pset->scene && PE_get_current(pset->scene, pset->scene_layer, pset->object));
}
static int rna_ParticleEdit_hair_get(PointerRNA *ptr)
{
ParticleEditSettings *pset = (ParticleEditSettings *)ptr->data;
if (pset->scene) {
- PTCacheEdit *edit = PE_get_current(pset->scene, pset->object);
+ PTCacheEdit *edit = PE_get_current(pset->scene, pset->scene_layer, pset->object);
return (edit && edit->psys);
}
@@ -329,9 +330,10 @@ static void rna_ImaPaint_viewport_update(Main *UNUSED(bmain), Scene *UNUSED(scen
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
-static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), bContext *C, Scene *scene, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
if (ob && ob->type == OB_MESH) {
/* of course we need to invalidate here */
@@ -344,9 +346,10 @@ static void rna_ImaPaint_mode_update(Main *UNUSED(bmain), Scene *scene, PointerR
}
}
-static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), bContext *C, Scene *scene, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
if (ob && ob->type == OB_MESH) {
GPU_drawobject_free(ob->derivedFinal);
@@ -355,19 +358,20 @@ static void rna_ImaPaint_stencil_update(Main *UNUSED(bmain), Scene *scene, Point
}
}
-static void rna_ImaPaint_canvas_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr))
+static void rna_ImaPaint_canvas_update(Main *bmain, bContext *C, Scene *scene, PointerRNA *UNUSED(ptr))
{
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
bScreen *sc;
Image *ima = scene->toolsettings->imapaint.canvas;
for (sc = bmain->screen.first; sc; sc = sc->id.next) {
ScrArea *sa;
for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_IMAGE) {
- SpaceImage *sima = (SpaceImage *)sl;
+ SpaceLink *slink;
+ for (slink = sa->spacedata.first; slink; slink = slink->next) {
+ if (slink->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)slink;
if (!sima->pin)
ED_space_image_set(sima, scene, scene->obedit, ima);
@@ -740,12 +744,12 @@ static void rna_def_image_paint(BlenderRNA *brna)
prop = RNA_def_property(srna, "stencil_image", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "stencil");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Stencil Image", "Image used as stencil");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_stencil_update");
prop = RNA_def_property(srna, "canvas", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Canvas", "Image used as canvas");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_canvas_update");
@@ -787,6 +791,7 @@ static void rna_def_image_paint(BlenderRNA *brna)
RNA_def_property_range(prop, 512, 16384);
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_items(prop, paint_type_items);
RNA_def_property_ui_text(prop, "Mode", "Mode of operation for projection painting");
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, "rna_ImaPaint_mode_update");
@@ -895,6 +900,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Auto Velocity", "Calculate point velocities automatically");
prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PE_DRAW_PART);
RNA_def_property_ui_text(prop, "Draw Particles", "Draw actual particles");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
@@ -915,16 +921,19 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Brush", "");
prop = RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Steps", "How many steps to draw the path with");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
prop = RNA_def_property(srna, "fade_frames", PROP_INT, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Frames", "How many frames to fade");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_update");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_sdna(prop, NULL, "edittype");
RNA_def_property_enum_items(prop, edit_type_items);
RNA_def_property_ui_text(prop, "Type", "");
@@ -945,7 +954,7 @@ static void rna_def_particle_edit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object", "The edited object");
prop = RNA_def_property(srna, "shape_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Shape Object", "Outer shape to use for tools");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_ParticleEdit_redo");
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 6db370fc152..c12937bd2bf 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -832,14 +832,14 @@ static void rna_def_smoke_domain_settings(BlenderRNA *brna)
{FLUID_FIELD_COLOR_R, "COLOR_R", 0, "Red", "Red component of the color field"},
{FLUID_FIELD_COLOR_G, "COLOR_G", 0, "Green", "Green component of the color field"},
{FLUID_FIELD_COLOR_B, "COLOR_B", 0, "Blue", "Blue component of the color field"},
- {FLUID_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
+ {FLUID_FIELD_DENSITY, "DENSITY", 0, "Density", "Quantity of soot in the fluid"},
{FLUID_FIELD_FLAME, "FLAME", 0, "Flame", "Flame field"},
{FLUID_FIELD_FUEL, "FUEL", 0, "Fuel", "Fuel field"},
{FLUID_FIELD_HEAT, "HEAT", 0, "Heat", "Temperature of the fluid"},
{FLUID_FIELD_VELOCITY_X, "VELOCITY_X", 0, "X Velocity", "X component of the velocity field"},
{FLUID_FIELD_VELOCITY_Y, "VELOCITY_Y", 0, "Y Velocity", "Y component of the velocity field"},
{FLUID_FIELD_VELOCITY_Z, "VELOCITY_Z", 0, "Z Velocity", "Z component of the velocity field"},
- {0, NULL, 0, NULL, NULL}
+ {0, NULL, 0, NULL, NULL}
};
prop = RNA_def_property(srna, "coba_field", PROP_ENUM, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index aa3346ec653..e8efb2426d1 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -79,7 +79,6 @@ EnumPropertyItem rna_enum_space_type_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{SPACE_BUTS, "PROPERTIES", ICON_BUTS, "Properties", "Edit properties of active object and related data-blocks"},
{SPACE_OUTLINER, "OUTLINER", ICON_OOPS, "Outliner", "Overview of scene graph and all available data-blocks"},
- {SPACE_COLLECTIONS, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collections", "Edit collections of active render layer"},
{SPACE_USERPREF, "USER_PREFERENCES", ICON_PREFERENCES, "User Preferences", "Edit persistent configuration settings"},
{SPACE_INFO, "INFO", ICON_INFO, "Info", "Main menu bar and list of error messages (drag down to expand and display)"},
{0, "", ICON_NONE, NULL, NULL},
@@ -258,6 +257,7 @@ EnumPropertyItem rna_enum_file_sort_items[] = {
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_depsgraph.h"
+#include "BKE_layer.h"
#include "BKE_nla.h"
#include "BKE_paint.h"
#include "BKE_scene.h"
@@ -319,8 +319,6 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
return &RNA_SpaceUserPreferences;
case SPACE_CLIP:
return &RNA_SpaceClipEditor;
- case SPACE_COLLECTIONS:
- return &RNA_SpaceCollectionManager;
default:
return &RNA_Space;
}
@@ -824,7 +822,11 @@ static int rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
bScreen *sc = (bScreen *)ptr->id.data;
- return ED_space_image_check_show_maskedit(sc->scene, sima);
+
+ TODO_LAYER_CONTEXT; /* get SceneLayer from context/window/workspace instead */
+ SceneLayer *sl = BKE_scene_layer_context_active(sc->scene);
+
+ return ED_space_image_check_show_maskedit(sl, sima);
}
static void rna_SpaceImageEditor_image_set(PointerRNA *ptr, PointerRNA value)
@@ -2112,7 +2114,9 @@ static void rna_def_space_outliner(BlenderRNA *brna)
{SO_USERDEF, "USER_PREFERENCES", 0, "User Preferences", "Display user preference data"},
{SO_ID_ORPHANS, "ORPHAN_DATA", 0, "Orphan Data",
"Display data-blocks which are unused and/or will be lost when the file is reloaded"},
- {SO_COLLECTIONS, "COLLECTIONS", 0, "Collections", "Display the collections of the active render layer"},
+ {SO_ACT_LAYER, "ACT_LAYER", 0, "Active Render Layer", "Display the collections of the active render layer"},
+ {SO_COLLECTIONS, "MASTER_COLLECTION", 0, "Master Collection Tree", "Display all collections based on the "
+ "master collection hierarchy"},
{0, NULL, 0, NULL, NULL}
};
@@ -4824,15 +4828,6 @@ static void rna_def_space_clip(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, NULL);
}
-static void rna_def_space_collections(BlenderRNA *brna)
-{
- StructRNA *srna;
-
- srna = RNA_def_struct(brna, "SpaceCollectionManager", "Space");
- RNA_def_struct_sdna(srna, "SpaceCollections");
- RNA_def_struct_ui_text(srna, "Space Collection Manager", "Layer Collection space data");
-}
-
void RNA_def_space(BlenderRNA *brna)
{
@@ -4859,7 +4854,6 @@ void RNA_def_space(BlenderRNA *brna)
rna_def_space_node(brna);
rna_def_space_logic(brna);
rna_def_space_clip(brna);
- rna_def_space_collections(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 1e88585a286..3a3359e1008 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -225,7 +225,7 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value)
BKE_texture_type_set(tex, value);
}
-void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+void rna_TextureSlot_update(Main *UNUSED(bmain), bContext *C, Scene *scene, PointerRNA *ptr)
{
ID *id = ptr->id.data;
@@ -246,7 +246,8 @@ void rna_TextureSlot_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
case ID_BR:
{
MTex *mtex = ptr->data;
- BKE_paint_invalidate_overlay_tex(scene, mtex->tex);
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ BKE_paint_invalidate_overlay_tex(scene, sl, mtex->tex);
WM_main_add_notifier(NC_BRUSH, id);
break;
}
@@ -645,7 +646,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tex");
RNA_def_property_struct_type(prop, "Texture");
- RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update");
@@ -653,6 +654,7 @@ static void rna_def_mtex(BlenderRNA *brna)
RNA_def_property_string_funcs(prop, "rna_TextureSlot_name_get", "rna_TextureSlot_name_length", NULL);
RNA_def_property_ui_text(prop, "Name", "Texture slot name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -660,12 +662,13 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "ofs");
RNA_def_property_ui_range(prop, -10, 10, 10, RNA_TRANSLATION_PREC_DEFAULT);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Offset", "Fine tune of the texture mapping X, Y and Z locations");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "scale", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "size");
- RNA_def_property_flag(prop, PROP_PROPORTIONAL);
+ RNA_def_property_flag(prop, PROP_PROPORTIONAL | PROP_CONTEXT_UPDATE);
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
RNA_def_property_ui_text(prop, "Size", "Set scaling for the texture's X, Y and Z sizes");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -673,6 +676,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "r");
RNA_def_property_array(prop, 3);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Color",
"Default color for textures that don't return RGB or when RGB to intensity is enabled");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
@@ -680,26 +684,31 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "blend_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "blendtype");
RNA_def_property_enum_items(prop, blend_type_items);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Blend Type", "Mode used to apply the texture");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_stencil", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_STENCIL);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Stencil", "Use this texture as a blending value on the next texture");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "invert", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_NEGATIVE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "Negate", "Invert the values of the texture to reverse its effect");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "use_rgb_to_intensity", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "texflag", MTEX_RGBTOINT);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_text(prop, "RGB to Intensity", "Convert texture RGB values to intensity (gray) values");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
prop = RNA_def_property(srna, "default_value", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "def_var");
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_ui_range(prop, 0, 1, 10, 3);
RNA_def_property_ui_text(prop, "Default Value",
"Value to use for Ref, Spec, Amb, Emit, Alpha, RayMir, TransLu and Hard");
@@ -708,6 +717,7 @@ static void rna_def_mtex(BlenderRNA *brna)
prop = RNA_def_property(srna, "output_node", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "which_output");
RNA_def_property_enum_items(prop, output_node_items);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_enum_funcs(prop, "rna_TextureSlot_output_node_get", NULL, "rna_TextureSlot_output_node_itemf");
RNA_def_property_ui_text(prop, "Output Node", "Which output node to use, for node-based textures");
RNA_def_property_update(prop, 0, "rna_TextureSlot_update");
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 46775af21db..6ef4bc6a371 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -888,6 +888,15 @@ void RNA_api_ui_layout(StructRNA *srna)
parm = RNA_def_pointer(func, "item", "KeyMapItem", "", "");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ func = RNA_def_function(srna, "template_override_property", "uiTemplateOverrideProperty");
+ parm = RNA_def_pointer(func, "collection_render_overrides", "AnyType", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_pointer(func, "scene_collection_properties", "AnyType", "", "");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ parm = RNA_def_string(func, "property", NULL, 0, "", "Identifier of property in collection_properties");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ parm = RNA_def_string(func, "custom_template", NULL, 0, "", "Optional template to use for property");
+
func = RNA_def_function(srna, "template_component_menu", "uiTemplateComponentMenu");
RNA_def_function_ui_description(func, "Item. Display expanded property in a popup menu");
parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 06b8e6e0737..5e52882b789 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -138,23 +138,11 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe
}
/* also used by buffer swap switching */
-static void rna_userdef_dpi_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+static void rna_userdef_dpi_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
/* font's are stored at each DPI level, without this we can easy load 100's of fonts */
BLF_cache_clear();
- BKE_blender_userdef_refresh();
- WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
- WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
-}
-
-static void rna_userdef_virtual_pixel_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
-{
- /* font's are stored at each DPI level, without this we can easy load 100's of fonts */
- BLF_cache_clear();
-
- BKE_blender_userdef_refresh();
-
/* force setting drawable again */
wmWindowManager *wm = bmain->wm.first;
if (wm) {
@@ -2956,26 +2944,6 @@ static void rna_def_userdef_theme_space_clip(BlenderRNA *brna)
rna_def_userdef_theme_spaces_curves(srna, false, false, false, true);
}
-static void rna_def_userdef_theme_space_collections(BlenderRNA *brna)
-{
- StructRNA *srna;
- PropertyRNA *prop;
-
- srna = RNA_def_struct(brna, "ThemeCollectionManager", NULL);
- RNA_def_struct_sdna(srna, "ThemeSpace");
- RNA_def_struct_clear_flag(srna, STRUCT_UNDO);
- RNA_def_struct_ui_text(srna, "Theme Collection Manager", "Theme settings for the Collection Manager");
-
- rna_def_userdef_theme_spaces_main(srna);
- rna_def_userdef_theme_spaces_list_main(srna);
-
- prop = RNA_def_property(srna, "selected_collection", PROP_FLOAT, PROP_COLOR_GAMMA);
- RNA_def_property_float_sdna(prop, NULL, "hilite");
- RNA_def_property_array(prop, 3);
- RNA_def_property_ui_text(prop, "Selected Collection", "");
- RNA_def_property_update(prop, 0, "rna_userdef_update");
-}
-
static void rna_def_userdef_themes(BlenderRNA *brna)
{
StructRNA *srna;
@@ -3002,7 +2970,6 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
{16, "FILE_BROWSER", ICON_FILESEL, "File Browser", ""},
{17, "CONSOLE", ICON_CONSOLE, "Python Console", ""},
{20, "CLIP_EDITOR", ICON_CLIP, "Movie Clip Editor", ""},
- {21, "COLLECTION_MANAGER", ICON_COLLAPSEMENU, "Collection Manager", ""},
{0, NULL, 0, NULL, NULL}
};
@@ -3136,12 +3103,6 @@ static void rna_def_userdef_themes(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "tclip");
RNA_def_property_struct_type(prop, "ThemeClipEditor");
RNA_def_property_ui_text(prop, "Clip Editor", "");
-
- prop = RNA_def_property(srna, "collection_manager", PROP_POINTER, PROP_NONE);
- RNA_def_property_flag(prop, PROP_NEVER_NULL);
- RNA_def_property_pointer_sdna(prop, NULL, "tcollections");
- RNA_def_property_struct_type(prop, "ThemeCollectionManager");
- RNA_def_property_ui_text(prop, "Collection Manager", "");
}
static void rna_def_userdef_addon(BlenderRNA *brna)
@@ -3232,7 +3193,6 @@ static void rna_def_userdef_dothemes(BlenderRNA *brna)
rna_def_userdef_theme_space_console(brna);
rna_def_userdef_theme_space_logic(brna);
rna_def_userdef_theme_space_clip(brna);
- rna_def_userdef_theme_space_collections(brna);
rna_def_userdef_theme_colorset(brna);
rna_def_userdef_themes(brna);
}
@@ -3353,6 +3313,12 @@ static void rna_def_userdef_view(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "View & Controls", "Preferences related to viewing data");
/* View */
+ prop = RNA_def_property(srna, "ui_scale", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_ui_text(prop, "UI Scale", "Changes the size of the fonts and buttons in the interface");
+ RNA_def_property_range(prop, 0.25f, 4.0f);
+ RNA_def_property_ui_range(prop, 0.5f, 2.0f, 1, 1);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
/* display */
prop = RNA_def_property(srna, "show_tooltips", PROP_BOOLEAN, PROP_NONE);
@@ -3944,12 +3910,6 @@ static void rna_def_userdef_system(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL}
};
- static EnumPropertyItem virtual_pixel_mode_items[] = {
- {VIRTUAL_PIXEL_NATIVE, "NATIVE", 0, "Native", "Use native pixel size of the display"},
- {VIRTUAL_PIXEL_DOUBLE, "DOUBLE", 0, "Double", "Use double the native pixel size of the display"},
- {0, NULL, 0, NULL, NULL}
- };
-
srna = RNA_def_struct(brna, "UserPreferencesSystem", NULL);
RNA_def_struct_sdna(srna, "UserDef");
RNA_def_struct_nested(brna, srna, "UserPreferences");
@@ -3964,16 +3924,8 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_update(prop, NC_WINDOW, "rna_userdef_language_update");
prop = RNA_def_property(srna, "dpi", PROP_INT, PROP_NONE);
- RNA_def_property_int_sdna(prop, NULL, "dpi");
- RNA_def_property_range(prop, 48, 144);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display");
- RNA_def_property_update(prop, 0, "rna_userdef_dpi_update");
-
- prop = RNA_def_property(srna, "virtual_pixel_mode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "virtual_pixel");
- RNA_def_property_enum_items(prop, virtual_pixel_mode_items);
- RNA_def_property_ui_text(prop, "Virtual Pixel Mode", "Modify the pixel size for hi-res devices");
- RNA_def_property_update(prop, 0, "rna_userdef_virtual_pixel_update");
prop = RNA_def_property(srna, "pixel_size", PROP_FLOAT, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@@ -4208,6 +4160,10 @@ static void rna_def_userdef_system(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Selection Method",
"Use OpenGL occlusion queries or selection render mode to accelerate selection");
+ prop = RNA_def_property(srna, "use_select_pick_depth", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "gpu_select_pick_deph", 1);
+ RNA_def_property_ui_text(prop, "OpenGL Depth Picking", "Use the depth buffer for picking 3D View selection");
+
/* Full scene anti-aliasing */
prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples");
@@ -4702,6 +4658,11 @@ void RNA_def_userdef(BlenderRNA *brna)
"Active section of the user preferences shown in the user interface");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ /* don't expose this directly via the UI, modify via an operator */
+ prop = RNA_def_property(srna, "app_template", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "app_template");
+ RNA_def_property_ui_text(prop, "Application Template", "");
+
prop = RNA_def_property(srna, "themes", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "themes", NULL);
RNA_def_property_struct_type(prop, "Theme");
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index 1f23ab938fb..677ea92aea1 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -87,6 +87,11 @@ static void rna_Operator_report(wmOperator *op, int type, const char *msg)
BKE_report(op->reports, type, msg);
}
+static int rna_Operator_is_repeat(wmOperator *op, bContext *C)
+{
+ return WM_operator_is_repeat(C, op);
+}
+
/* since event isn't needed... */
static void rna_Operator_enum_search_invoke(bContext *C, wmOperator *op)
{
@@ -521,6 +526,12 @@ void RNA_api_operator(StructRNA *srna)
parm = RNA_def_string(func, "message", NULL, 0, "Report Message", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ /* utility, not for registering */
+ func = RNA_def_function(srna, "is_repeat", "rna_Operator_is_repeat");
+ RNA_def_function_flag(func, FUNC_USE_CONTEXT);
+ /* return */
+ parm = RNA_def_boolean(func, "result", 0, "result", "");
+ RNA_def_function_return(func, parm);
/* Registration */
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index b8ebb375a48..15a7ea5d644 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -93,6 +93,7 @@ set(SRC
intern/MOD_solidify.c
intern/MOD_subsurf.c
intern/MOD_surface.c
+ intern/MOD_surfacedeform.c
intern/MOD_triangulate.c
intern/MOD_util.c
intern/MOD_uvwarp.c
diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h
index 4c881445893..bf121af2bd1 100644
--- a/source/blender/modifiers/MOD_modifiertypes.h
+++ b/source/blender/modifiers/MOD_modifiertypes.h
@@ -85,6 +85,7 @@ extern ModifierTypeInfo modifierType_DataTransfer;
extern ModifierTypeInfo modifierType_NormalEdit;
extern ModifierTypeInfo modifierType_CorrectiveSmooth;
extern ModifierTypeInfo modifierType_MeshSequenceCache;
+extern ModifierTypeInfo modifierType_SurfaceDeform;
/* MOD_util.c */
void modifier_type_init(ModifierTypeInfo *types[]);
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 51020566de6..6aadd10480e 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -303,6 +303,7 @@ static DerivedMesh *applyModifier_bmesh(
use_separate,
use_dissolve,
use_island_connect,
+ false,
bmd->operation,
bmd->double_threshold);
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 43e7ac238d1..4f875bbf35f 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -300,7 +300,7 @@ static void displaceModifier_do(
float (*tex_co)[3];
float weight = 1.0f; /* init value unused but some compilers may complain */
float (*vert_clnors)[3] = NULL;
- float local_mat[4][4] = {0};
+ float local_mat[4][4] = {{0}};
const bool use_global_direction = dmd->space == MOD_DISP_SPACE_GLOBAL;
if (!dmd->texture && dmd->direction == MOD_DISP_DIR_RGB_XYZ) return;
diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c
index 794d8bf6951..9eb3e673f27 100644
--- a/source/blender/modifiers/intern/MOD_dynamicpaint.c
+++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c
@@ -116,7 +116,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
static bool is_brush_cb(Object *UNUSED(ob), ModifierData *pmd)
{
- return ((DynamicPaintModifierData*)pmd)->brush != NULL;
+ return ((DynamicPaintModifierData *)pmd)->brush != NULL;
}
static void updateDepsgraph(ModifierData *md,
diff --git a/source/blender/modifiers/intern/MOD_fluidsim.c b/source/blender/modifiers/intern/MOD_fluidsim.c
index 35e9afe722b..9e91a76ecb8 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim.c
@@ -41,6 +41,7 @@
#include "BKE_cdderivedmesh.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "depsgraph_private.h"
@@ -109,9 +110,8 @@ static void updateDepsgraph(ModifierData *md,
FluidsimModifierData *fluidmd = (FluidsimModifierData *) md;
if (fluidmd && fluidmd->fss) {
if (fluidmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- BaseLegacy *base;
- for (base = scene->base.first; base; base = base->next) {
- Object *ob1 = base->object;
+ FOREACH_SCENE_OBJECT(scene, ob1)
+ {
if (ob1 != ob) {
FluidsimModifierData *fluidmdtmp =
(FluidsimModifierData *)modifiers_findByType(ob1, eModifierType_Fluidsim);
@@ -122,6 +122,7 @@ static void updateDepsgraph(ModifierData *md,
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c
index 8c01c560e75..39da0dacd8f 100644
--- a/source/blender/modifiers/intern/MOD_mirror.c
+++ b/source/blender/modifiers/intern/MOD_mirror.c
@@ -259,8 +259,8 @@ static DerivedMesh *doMirrorOnAxis(MirrorModifierData *mmd,
int j = maxLoops;
dmloopuv += j; /* second set of loops only */
for (; j-- > 0; dmloopuv++) {
- if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0];
- if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1];
+ if (do_mirr_u) dmloopuv->uv[0] = 1.0f - dmloopuv->uv[0] + mmd->uv_offset[0];
+ if (do_mirr_v) dmloopuv->uv[1] = 1.0f - dmloopuv->uv[1] + mmd->uv_offset[1];
}
}
}
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index fc02a2e1327..ea68f540236 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -172,6 +172,7 @@ ModifierTypeInfo modifierType_Surface = {
/* structSize */ sizeof(SurfaceModifierData),
/* type */ eModifierTypeType_OnlyDeform,
/* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_AcceptsCVs |
eModifierTypeFlag_NoUserAdd,
/* copyData */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
new file mode 100644
index 00000000000..a0a5760180d
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -0,0 +1,1210 @@
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_alloca.h"
+#include "BLI_math.h"
+#include "BLI_math_geom.h"
+#include "BLI_task.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_editmesh.h"
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+
+#include "depsgraph_private.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "MOD_util.h"
+
+typedef struct SDefAdjacency {
+ struct SDefAdjacency *next;
+ unsigned int index;
+} SDefAdjacency;
+
+typedef struct SDefAdjacencyArray {
+ SDefAdjacency *first;
+ unsigned int num; /* Careful, this is twice the number of polygons (avoids an extra loop) */
+} SDefAdjacencyArray;
+
+typedef struct SDefEdgePolys {
+ unsigned int polys[2], num;
+} SDefEdgePolys;
+
+typedef struct SDefBindCalcData {
+ BVHTreeFromMesh * const treeData;
+ const SDefAdjacencyArray * const vert_edges;
+ const SDefEdgePolys * const edge_polys;
+ SDefVert * const bind_verts;
+ const MLoopTri * const looptri;
+ const MPoly * const mpoly;
+ const MEdge * const medge;
+ const MLoop * const mloop;
+ float (* const targetCos)[3];
+ float (* const vertexCos)[3];
+ float imat[4][4];
+ const float falloff;
+ int success;
+} SDefBindCalcData;
+
+typedef struct SDefBindPoly {
+ float (*coords)[3];
+ float (*coords_v2)[2];
+ float point_v2[2];
+ float weight_angular;
+ float weight_dist_proj;
+ float weight_dist;
+ float weight;
+ float scales[2];
+ float centroid[3];
+ float centroid_v2[2];
+ float normal[3];
+ float cent_edgemid_vecs_v2[2][2];
+ float edgemid_angle;
+ float point_edgemid_angles[2];
+ float corner_edgemid_angles[2];
+ float dominant_angle_weight;
+ unsigned int index;
+ unsigned int numverts;
+ unsigned int loopstart;
+ unsigned int edge_inds[2];
+ unsigned int edge_vert_inds[2];
+ unsigned int corner_ind;
+ unsigned int dominant_edge;
+ bool inside;
+} SDefBindPoly;
+
+typedef struct SDefBindWeightData {
+ SDefBindPoly *bind_polys;
+ unsigned int numpoly;
+ unsigned int numbinds;
+} SDefBindWeightData;
+
+typedef struct SDefDeformData {
+ const SDefVert * const bind_verts;
+ float (* const targetCos)[3];
+ float (* const vertexCos)[3];
+} SDefDeformData;
+
+/* Bind result values */
+enum {
+ MOD_SDEF_BIND_RESULT_SUCCESS = 1,
+ MOD_SDEF_BIND_RESULT_GENERIC_ERR = 0,
+ MOD_SDEF_BIND_RESULT_MEM_ERR = -1,
+ MOD_SDEF_BIND_RESULT_NONMANY_ERR = -2,
+ MOD_SDEF_BIND_RESULT_CONCAVE_ERR = -3,
+ MOD_SDEF_BIND_RESULT_OVERLAP_ERR = -4,
+};
+
+/* Infinite weight flags */
+enum {
+ MOD_SDEF_INFINITE_WEIGHT_ANGULAR = (1 << 0),
+ MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ = (1 << 1),
+ MOD_SDEF_INFINITE_WEIGHT_DIST = (1 << 2),
+};
+
+static void initData(ModifierData *md)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ smd->target = NULL;
+ smd->verts = NULL;
+ smd->flags = 0;
+ smd->falloff = 4.0f;
+}
+
+static void freeData(ModifierData *md)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ if (smd->verts) {
+ for (int i = 0; i < smd->numverts; i++) {
+ if (smd->verts[i].binds) {
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ MEM_SAFE_FREE(smd->verts[i].binds[j].vert_inds);
+ MEM_SAFE_FREE(smd->verts[i].binds[j].vert_weights);
+ }
+
+ MEM_freeN(smd->verts[i].binds);
+ }
+ }
+
+ MEM_freeN(smd->verts);
+ smd->verts = NULL;
+ }
+}
+
+static void copyData(ModifierData *md, ModifierData *target)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target;
+
+ *tsmd = *smd;
+
+ if (smd->verts) {
+ tsmd->verts = MEM_dupallocN(smd->verts);
+
+ for (int i = 0; i < smd->numverts; i++) {
+ if (smd->verts[i].binds) {
+ tsmd->verts[i].binds = MEM_dupallocN(smd->verts[i].binds);
+
+ for (int j = 0; j < smd->verts[i].numbinds; j++) {
+ if (smd->verts[i].binds[j].vert_inds) {
+ tsmd->verts[i].binds[j].vert_inds = MEM_dupallocN(smd->verts[i].binds[j].vert_inds);
+ }
+
+ if (smd->verts[i].binds[j].vert_weights) {
+ tsmd->verts[i].binds[j].vert_weights = MEM_dupallocN(smd->verts[i].binds[j].vert_weights);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ walk(userData, ob, &smd->target, IDWALK_NOP);
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ if (smd->target != NULL) {
+ DEG_add_object_relation(node, smd->target, DEG_OB_COMP_GEOMETRY, "Surface Deform Modifier");
+ }
+}
+
+static void freeAdjacencyMap(SDefAdjacencyArray * const vert_edges, SDefAdjacency * const adj_ref, SDefEdgePolys * const edge_polys)
+{
+ MEM_freeN(edge_polys);
+
+ MEM_freeN(adj_ref);
+
+ MEM_freeN(vert_edges);
+}
+
+static int buildAdjacencyMap(const MPoly *poly, const MEdge *edge, const MLoop * const mloop, const unsigned int numpoly, const unsigned int numedges,
+ SDefAdjacencyArray * const vert_edges, SDefAdjacency *adj, SDefEdgePolys * const edge_polys)
+{
+ const MLoop *loop;
+
+ /* Fing polygons adjacent to edges */
+ for (int i = 0; i < numpoly; i++, poly++) {
+ loop = &mloop[poly->loopstart];
+
+ for (int j = 0; j < poly->totloop; j++, loop++) {
+ if (edge_polys[loop->e].num == 0) {
+ edge_polys[loop->e].polys[0] = i;
+ edge_polys[loop->e].polys[1] = -1;
+ edge_polys[loop->e].num++;
+ }
+ else if (edge_polys[loop->e].num == 1) {
+ edge_polys[loop->e].polys[1] = i;
+ edge_polys[loop->e].num++;
+ }
+ else {
+ return MOD_SDEF_BIND_RESULT_NONMANY_ERR;
+ }
+ }
+ }
+
+ /* Find edges adjacent to vertices */
+ for (int i = 0; i < numedges; i++, edge++) {
+ adj->next = vert_edges[edge->v1].first;
+ adj->index = i;
+ vert_edges[edge->v1].first = adj;
+ vert_edges[edge->v1].num += edge_polys[i].num;
+ adj++;
+
+ adj->next = vert_edges[edge->v2].first;
+ adj->index = i;
+ vert_edges[edge->v2].first = adj;
+ vert_edges[edge->v2].num += edge_polys[i].num;
+ adj++;
+ }
+
+ return MOD_SDEF_BIND_RESULT_SUCCESS;
+}
+
+BLI_INLINE void sortPolyVertsEdge(unsigned int *indices, const MLoop * const mloop, const unsigned int edge, const unsigned int num)
+{
+ bool found = false;
+
+ for (int i = 0; i < num; i++) {
+ if (mloop[i].e == edge) {
+ found = true;
+ }
+ if (found) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+ }
+
+ /* Fill in remaining vertex indices that occur before the edge */
+ for (int i = 0; mloop[i].e != edge; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+}
+
+BLI_INLINE void sortPolyVertsTri(unsigned int *indices, const MLoop * const mloop, const unsigned int loopstart, const unsigned int num)
+{
+ for (int i = loopstart; i < num; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+
+ for (int i = 0; i < loopstart; i++) {
+ *indices = mloop[i].v;
+ indices++;
+ }
+}
+
+BLI_INLINE unsigned int nearestVert(SDefBindCalcData * const data, const float point_co[3])
+{
+ BVHTreeNearest nearest = {.dist_sq = FLT_MAX, .index = -1};
+ const MPoly *poly;
+ const MEdge *edge;
+ const MLoop *loop;
+ float t_point[3];
+ float max_dist = FLT_MAX;
+ float dist;
+ unsigned int index = 0;
+
+ mul_v3_m4v3(t_point, data->imat, point_co);
+
+ BLI_bvhtree_find_nearest(data->treeData->tree, t_point, &nearest, data->treeData->nearest_callback, data->treeData);
+
+ poly = &data->mpoly[data->looptri[nearest.index].poly];
+ loop = &data->mloop[poly->loopstart];
+
+ for (int i = 0; i < poly->totloop; i++, loop++) {
+ edge = &data->medge[loop->e];
+ dist = dist_squared_to_line_segment_v3(point_co, data->targetCos[edge->v1], data->targetCos[edge->v2]);
+
+ if (dist < max_dist) {
+ max_dist = dist;
+ index = loop->e;
+ }
+ }
+
+ edge = &data->medge[index];
+ if (len_squared_v3v3(point_co, data->targetCos[edge->v1]) < len_squared_v3v3(point_co, data->targetCos[edge->v2])) {
+ return edge->v1;
+ }
+ else {
+ return edge->v2;
+ }
+}
+
+BLI_INLINE int isPolyValid(const float coords[][2], const unsigned int nr)
+{
+ float prev_co[2];
+ float curr_vec[2], prev_vec[2];
+
+ if (!is_poly_convex_v2(coords, nr)) {
+ return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
+ }
+
+ copy_v2_v2(prev_co, coords[nr - 1]);
+ sub_v2_v2v2(prev_vec, prev_co, coords[nr - 2]);
+
+ for (int i = 0; i < nr; i++) {
+ sub_v2_v2v2(curr_vec, coords[i], prev_co);
+
+ if (len_squared_v2(curr_vec) < FLT_EPSILON) {
+ return MOD_SDEF_BIND_RESULT_OVERLAP_ERR;
+ }
+
+ if (1.0f - dot_v2v2(prev_vec, curr_vec) < FLT_EPSILON) {
+ return MOD_SDEF_BIND_RESULT_CONCAVE_ERR;
+ }
+
+ copy_v2_v2(prev_co, coords[i]);
+ copy_v2_v2(prev_vec, curr_vec);
+ }
+
+ return MOD_SDEF_BIND_RESULT_SUCCESS;
+}
+
+static void freeBindData(SDefBindWeightData * const bwdata)
+{
+ SDefBindPoly *bpoly = bwdata->bind_polys;
+
+ if (bwdata->bind_polys) {
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ MEM_SAFE_FREE(bpoly->coords);
+ MEM_SAFE_FREE(bpoly->coords_v2);
+ }
+
+ MEM_freeN(bwdata->bind_polys);
+ }
+
+ MEM_freeN(bwdata);
+}
+
+BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
+{
+ float weight;
+
+ weight = point_angle;
+ weight /= edgemid_angle;
+ weight *= M_PI_2;
+
+ return sinf(weight);
+}
+
+BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData * const data, const float point_co[3])
+{
+ const unsigned int nearest = nearestVert(data, point_co);
+ const SDefAdjacency * const vert_edges = data->vert_edges[nearest].first;
+ const SDefEdgePolys * const edge_polys = data->edge_polys;
+
+ const SDefAdjacency *vedge;
+ const MPoly *poly;
+ const MLoop *loop;
+
+ SDefBindWeightData *bwdata;
+ SDefBindPoly *bpoly;
+
+ float world[3] = {0.0f, 0.0f, 1.0f};
+ float avg_point_dist = 0.0f;
+ float tot_weight = 0.0f;
+ int inf_weight_flags = 0;
+
+ bwdata = MEM_callocN(sizeof(*bwdata), "SDefBindWeightData");
+ if (bwdata == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bwdata->numpoly = data->vert_edges[nearest].num / 2;
+
+ bpoly = MEM_callocN(sizeof(*bpoly) * bwdata->numpoly, "SDefBindPoly");
+ if (bpoly == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bwdata->bind_polys = bpoly;
+
+ /* Loop over all adjacent edges, and build the SDefBindPoly data for each poly adjacent to those */
+ for (vedge = vert_edges; vedge; vedge = vedge->next) {
+ unsigned int edge_ind = vedge->index;
+
+ for (int i = 0; i < edge_polys[edge_ind].num; i++) {
+ {
+ bpoly = bwdata->bind_polys;
+
+ for (int j = 0; j < bwdata->numpoly; bpoly++, j++) {
+ /* If coords isn't allocated, we have reached the first uninitialized bpoly */
+ if ((bpoly->index == edge_polys[edge_ind].polys[i]) || (!bpoly->coords)) {
+ break;
+ }
+ }
+ }
+
+ /* Check if poly was already created by another edge or still has to be initialized */
+ if (!bpoly->coords) {
+ float angle;
+ float axis[3];
+ float tmp_vec_v2[2];
+ int is_poly_valid;
+
+ bpoly->index = edge_polys[edge_ind].polys[i];
+ bpoly->coords = NULL;
+ bpoly->coords_v2 = NULL;
+
+ /* Copy poly data */
+ poly = &data->mpoly[bpoly->index];
+ loop = &data->mloop[poly->loopstart];
+
+ bpoly->numverts = poly->totloop;
+ bpoly->loopstart = poly->loopstart;
+
+ bpoly->coords = MEM_mallocN(sizeof(*bpoly->coords) * poly->totloop, "SDefBindPolyCoords");
+ if (bpoly->coords == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ bpoly->coords_v2 = MEM_mallocN(sizeof(*bpoly->coords_v2) * poly->totloop, "SDefBindPolyCoords_v2");
+ if (bpoly->coords_v2 == NULL) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return NULL;
+ }
+
+ for (int j = 0; j < poly->totloop; j++, loop++) {
+ copy_v3_v3(bpoly->coords[j], data->targetCos[loop->v]);
+
+ /* Find corner and edge indices within poly loop array */
+ if (loop->v == nearest) {
+ bpoly->corner_ind = j;
+ bpoly->edge_vert_inds[0] = (j == 0) ? (poly->totloop - 1) : (j - 1);
+ bpoly->edge_vert_inds[1] = (j == poly->totloop - 1) ? (0) : (j + 1);
+
+ bpoly->edge_inds[0] = data->mloop[poly->loopstart + bpoly->edge_vert_inds[0]].e;
+ bpoly->edge_inds[1] = loop->e;
+ }
+ }
+
+ /* Compute poly's parametric data */
+ mid_v3_v3_array(bpoly->centroid, bpoly->coords, poly->totloop);
+ normal_poly_v3(bpoly->normal, bpoly->coords, poly->totloop);
+
+ /* Compute poly skew angle and axis */
+ angle = angle_normalized_v3v3(bpoly->normal, world);
+
+ cross_v3_v3v3(axis, bpoly->normal, world);
+ normalize_v3(axis);
+
+ /* Map coords onto 2d normal plane */
+ map_to_plane_axis_angle_v2_v3v3fl(bpoly->point_v2, point_co, axis, angle);
+
+ zero_v2(bpoly->centroid_v2);
+ for (int j = 0; j < poly->totloop; j++) {
+ map_to_plane_axis_angle_v2_v3v3fl(bpoly->coords_v2[j], bpoly->coords[j], axis, angle);
+ madd_v2_v2fl(bpoly->centroid_v2, bpoly->coords_v2[j], 1.0f / poly->totloop);
+ }
+
+ is_poly_valid = isPolyValid(bpoly->coords_v2, poly->totloop);
+
+ if (is_poly_valid != MOD_SDEF_BIND_RESULT_SUCCESS) {
+ freeBindData(bwdata);
+ data->success = is_poly_valid;
+ return NULL;
+ }
+
+ bpoly->inside = isect_point_poly_v2(bpoly->point_v2, bpoly->coords_v2, poly->totloop, false);
+
+ /* Initialize weight components */
+ bpoly->weight_angular = 1.0f;
+ bpoly->weight_dist_proj = len_v2v2(bpoly->centroid_v2, bpoly->point_v2);
+ bpoly->weight_dist = len_v3v3(bpoly->centroid, point_co);
+
+ avg_point_dist += bpoly->weight_dist;
+
+ /* Compute centroid to mid-edge vectors */
+ mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[0],
+ bpoly->coords_v2[bpoly->edge_vert_inds[0]],
+ bpoly->coords_v2[bpoly->corner_ind]);
+
+ mid_v2_v2v2(bpoly->cent_edgemid_vecs_v2[1],
+ bpoly->coords_v2[bpoly->edge_vert_inds[1]],
+ bpoly->coords_v2[bpoly->corner_ind]);
+
+ sub_v2_v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->centroid_v2);
+ sub_v2_v2(bpoly->cent_edgemid_vecs_v2[1], bpoly->centroid_v2);
+
+ /* Compute poly scales with respect to mid-edges, and normalize the vectors */
+ bpoly->scales[0] = normalize_v2(bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->scales[1] = normalize_v2(bpoly->cent_edgemid_vecs_v2[1]);
+
+ /* Compute the required polygon angles */
+ bpoly->edgemid_angle = angle_normalized_v2v2(bpoly->cent_edgemid_vecs_v2[0], bpoly->cent_edgemid_vecs_v2[1]);
+
+ sub_v2_v2v2(tmp_vec_v2, bpoly->coords_v2[bpoly->corner_ind], bpoly->centroid_v2);
+ normalize_v2(tmp_vec_v2);
+
+ bpoly->corner_edgemid_angles[0] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->corner_edgemid_angles[1] = angle_normalized_v2v2(tmp_vec_v2, bpoly->cent_edgemid_vecs_v2[1]);
+
+ /* Check for inifnite weights, and compute angular data otherwise */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ else if (bpoly->weight_dist_proj < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ }
+ else {
+ float cent_point_vec[2];
+
+ sub_v2_v2v2(cent_point_vec, bpoly->point_v2, bpoly->centroid_v2);
+ normalize_v2(cent_point_vec);
+
+ bpoly->point_edgemid_angles[0] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[0]);
+ bpoly->point_edgemid_angles[1] = angle_normalized_v2v2(cent_point_vec, bpoly->cent_edgemid_vecs_v2[1]);
+ }
+ }
+ }
+ }
+
+ avg_point_dist /= bwdata->numpoly;
+
+ /* If weights 1 and 2 are not infinite, loop over all adjacent edges again,
+ * and build adjacency dependent angle data (depends on all polygons having been computed) */
+ if (!inf_weight_flags) {
+ for (vedge = vert_edges; vedge; vedge = vedge->next) {
+ SDefBindPoly *bpolys[2];
+ const SDefEdgePolys *epolys;
+ float ang_weights[2];
+ unsigned int edge_ind = vedge->index;
+ unsigned int edge_on_poly[2];
+
+ epolys = &edge_polys[edge_ind];
+
+ /* Find bind polys corresponding to the edge's adjacent polys */
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0, j = 0; (i < bwdata->numpoly) && (j < epolys->num); bpoly++, i++) {
+ if (ELEM(bpoly->index, epolys->polys[0], epolys->polys[1])) {
+ bpolys[j] = bpoly;
+
+ if (bpoly->edge_inds[0] == edge_ind) {
+ edge_on_poly[j] = 0;
+ }
+ else {
+ edge_on_poly[j] = 1;
+ }
+
+ j++;
+ }
+ }
+
+ /* Compute angular weight component */
+ if (epolys->num == 1) {
+ ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
+ bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
+ }
+ else if (epolys->num == 2) {
+ ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]], bpolys[0]->edgemid_angle);
+ ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]], bpolys[1]->edgemid_angle);
+
+ bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
+ bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
+ }
+ }
+ }
+
+ /* Compute scalings and falloff.
+ * Scale all weights if no infinite weight is found,
+ * scale only unprojected weight if projected weight is infinite,
+ * scale none if both are infinite. */
+ if (!inf_weight_flags) {
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ float corner_angle_weights[2];
+ float scale_weight, sqr, inv_sqr;
+
+ corner_angle_weights[0] = bpoly->point_edgemid_angles[0] / bpoly->corner_edgemid_angles[0];
+ corner_angle_weights[1] = bpoly->point_edgemid_angles[1] / bpoly->corner_edgemid_angles[1];
+
+ if (isnan(corner_angle_weights[0]) || isnan(corner_angle_weights[1])) {
+ freeBindData(bwdata);
+ data->success = MOD_SDEF_BIND_RESULT_GENERIC_ERR;
+ return NULL;
+ }
+
+ /* Find which edge the point is closer to */
+ if (corner_angle_weights[0] < corner_angle_weights[1]) {
+ bpoly->dominant_edge = 0;
+ bpoly->dominant_angle_weight = corner_angle_weights[0];
+ }
+ else {
+ bpoly->dominant_edge = 1;
+ bpoly->dominant_angle_weight = corner_angle_weights[1];
+ }
+
+ bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
+
+ /* Compute quadratic angular scale interpolation weight */
+ scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle;
+ scale_weight /= scale_weight + (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle);
+
+ sqr = scale_weight * scale_weight;
+ inv_sqr = 1.0f - scale_weight;
+ inv_sqr *= inv_sqr;
+ scale_weight = sqr / (sqr + inv_sqr);
+
+ /* Compute interpolated scale (no longer need the individual scales,
+ * so simply storing the result over the scale in index zero) */
+ bpoly->scales[0] = bpoly->scales[bpoly->dominant_edge] * (1.0f - scale_weight) +
+ bpoly->scales[!bpoly->dominant_edge] * scale_weight;
+
+ /* Scale the point distance weights, and introduce falloff */
+ bpoly->weight_dist_proj /= bpoly->scales[0];
+ bpoly->weight_dist_proj = powf(bpoly->weight_dist_proj, data->falloff);
+
+ bpoly->weight_dist /= avg_point_dist;
+ bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
+
+ /* Re-check for infinite weights, now that all scalings and interpolations are computed */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ else if (bpoly->weight_dist_proj < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ;
+ }
+ else if (bpoly->weight_angular < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_ANGULAR;
+ }
+ }
+ }
+ else if (!(inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST)) {
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ /* Scale the point distance weight by average point distance, and introduce falloff */
+ bpoly->weight_dist /= avg_point_dist;
+ bpoly->weight_dist = powf(bpoly->weight_dist, data->falloff);
+
+ /* Re-check for infinite weights, now that all scalings and interpolations are computed */
+ if (bpoly->weight_dist < FLT_EPSILON) {
+ inf_weight_flags |= MOD_SDEF_INFINITE_WEIGHT_DIST;
+ }
+ }
+ }
+
+ /* Final loop, to compute actual weights */
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ /* Weight computation from components */
+ if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST) {
+ bpoly->weight = bpoly->weight_dist < FLT_EPSILON ? 1.0f : 0.0f;
+ }
+ else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_DIST_PROJ) {
+ bpoly->weight = bpoly->weight_dist_proj < FLT_EPSILON ?
+ 1.0f / bpoly->weight_dist : 0.0f;
+ }
+ else if (inf_weight_flags & MOD_SDEF_INFINITE_WEIGHT_ANGULAR) {
+ bpoly->weight = bpoly->weight_angular < FLT_EPSILON ?
+ 1.0f / bpoly->weight_dist_proj / bpoly->weight_dist : 0.0f;
+ }
+ else {
+ bpoly->weight = 1.0f / bpoly->weight_angular /
+ bpoly->weight_dist_proj /
+ bpoly->weight_dist;
+ }
+
+ tot_weight += bpoly->weight;
+ }
+
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numpoly; bpoly++, i++) {
+ bpoly->weight /= tot_weight;
+
+ /* Evaluate if this poly is relevant to bind */
+ /* Even though the weights should add up to 1.0,
+ * the losses of weights smaller than epsilon here
+ * should be negligible... */
+ if (bpoly->weight >= FLT_EPSILON) {
+ if (bpoly->inside) {
+ bwdata->numbinds += 1;
+ }
+ else {
+ if (bpoly->dominant_angle_weight < FLT_EPSILON || 1.0f - bpoly->dominant_angle_weight < FLT_EPSILON) {
+ bwdata->numbinds += 1;
+ }
+ else {
+ bwdata->numbinds += 2;
+ }
+ }
+ }
+ }
+
+ return bwdata;
+}
+
+BLI_INLINE float computeNormalDisplacement(const float point_co[3], const float point_co_proj[3], const float normal[3])
+{
+ float disp_vec[3];
+ float normal_dist;
+
+ sub_v3_v3v3(disp_vec, point_co, point_co_proj);
+ normal_dist = len_v3(disp_vec);
+
+ if (dot_v3v3(disp_vec, normal) < 0) {
+ normal_dist *= -1;
+ }
+
+ return normal_dist;
+}
+
+static void bindVert(void *userdata, void *UNUSED(userdata_chunk), const int index, const int UNUSED(threadid))
+{
+ SDefBindCalcData * const data = (SDefBindCalcData *)userdata;
+ float point_co[3];
+ float point_co_proj[3];
+
+ SDefBindWeightData *bwdata;
+ SDefVert *sdvert = data->bind_verts + index;
+ SDefBindPoly *bpoly;
+ SDefBind *sdbind;
+
+ if (data->success != MOD_SDEF_BIND_RESULT_SUCCESS) {
+ sdvert->binds = NULL;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ copy_v3_v3(point_co, data->vertexCos[index]);
+ bwdata = computeBindWeights(data, point_co);
+
+ if (bwdata == NULL) {
+ sdvert->binds = NULL;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ sdvert->binds = MEM_callocN(sizeof(*sdvert->binds) * bwdata->numbinds, "SDefVertBindData");
+ if (sdvert->binds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ sdvert->numbinds = 0;
+ return;
+ }
+
+ sdvert->numbinds = bwdata->numbinds;
+
+ sdbind = sdvert->binds;
+
+ bpoly = bwdata->bind_polys;
+
+ for (int i = 0; i < bwdata->numbinds; bpoly++) {
+ if (bpoly->weight >= FLT_EPSILON) {
+ if (bpoly->inside) {
+ const MLoop *loop = &data->mloop[bpoly->loopstart];
+
+ sdbind->influence = bpoly->weight;
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_NGON;
+ sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * bpoly->numverts, "SDefNgonVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefNgonVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ interp_weights_poly_v2(sdbind->vert_weights, bpoly->coords_v2, bpoly->numverts, bpoly->point_v2);
+
+ /* Reproject vert based on weights and original poly verts, to reintroduce poly non-planarity */
+ zero_v3(point_co_proj);
+ for (int j = 0; j < bpoly->numverts; j++, loop++) {
+ madd_v3_v3fl(point_co_proj, bpoly->coords[j], sdbind->vert_weights[j]);
+ sdbind->vert_inds[j] = loop->v;
+ }
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+ else {
+ float tmp_vec[3];
+ float cent[3], norm[3];
+ float v1[3], v2[3], v3[3];
+
+ if (1.0f - bpoly->dominant_angle_weight >= FLT_EPSILON) {
+ sdbind->influence = bpoly->weight * (1.0f - bpoly->dominant_angle_weight);
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_CENTROID;
+ sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * 3, "SDefCentVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefCentVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sortPolyVertsEdge(sdbind->vert_inds, &data->mloop[bpoly->loopstart],
+ bpoly->edge_inds[bpoly->dominant_edge], bpoly->numverts);
+
+ copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
+ copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
+ copy_v3_v3(v3, bpoly->centroid);
+
+ mid_v3_v3v3v3(cent, v1, v2, v3);
+ normal_tri_v3(norm, v1, v2, v3);
+
+ add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
+
+ /* We are sure the line is not parallel to the plane.
+ * Checking return value just to avoid warning... */
+ if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
+ BLI_assert(false);
+ }
+
+ interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+
+ if (bpoly->dominant_angle_weight >= FLT_EPSILON) {
+ sdbind->influence = bpoly->weight * bpoly->dominant_angle_weight;
+ sdbind->numverts = bpoly->numverts;
+
+ sdbind->mode = MOD_SDEF_MODE_LOOPTRI;
+ sdbind->vert_weights = MEM_mallocN(sizeof(*sdbind->vert_weights) * 3, "SDefTriVertWeights");
+ if (sdbind->vert_weights == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sdbind->vert_inds = MEM_mallocN(sizeof(*sdbind->vert_inds) * bpoly->numverts, "SDefTriVertInds");
+ if (sdbind->vert_inds == NULL) {
+ data->success = MOD_SDEF_BIND_RESULT_MEM_ERR;
+ return;
+ }
+
+ sortPolyVertsTri(sdbind->vert_inds, &data->mloop[bpoly->loopstart], bpoly->edge_vert_inds[0], bpoly->numverts);
+
+ copy_v3_v3(v1, data->targetCos[sdbind->vert_inds[0]]);
+ copy_v3_v3(v2, data->targetCos[sdbind->vert_inds[1]]);
+ copy_v3_v3(v3, data->targetCos[sdbind->vert_inds[2]]);
+
+ mid_v3_v3v3v3(cent, v1, v2, v3);
+ normal_tri_v3(norm, v1, v2, v3);
+
+ add_v3_v3v3(tmp_vec, point_co, bpoly->normal);
+
+ /* We are sure the line is not parallel to the plane.
+ * Checking return value just to avoid warning... */
+ if (!isect_line_plane_v3(point_co_proj, point_co, tmp_vec, cent, norm)) {
+ BLI_assert(false);
+ }
+
+ interp_weights_tri_v3(sdbind->vert_weights, v1, v2, v3, point_co_proj);
+
+ sdbind->normal_dist = computeNormalDisplacement(point_co, point_co_proj, bpoly->normal);
+
+ sdbind++;
+ i++;
+ }
+ }
+ }
+ }
+
+ freeBindData(bwdata);
+}
+
+static bool surfacedeformBind(SurfaceDeformModifierData *smd, float (*vertexCos)[3],
+ unsigned int numverts, unsigned int tnumpoly, unsigned int tnumverts, DerivedMesh *tdm)
+{
+ BVHTreeFromMesh treeData = {NULL};
+ const MVert *mvert = tdm->getVertArray(tdm);
+ const MPoly *mpoly = tdm->getPolyArray(tdm);
+ const MEdge *medge = tdm->getEdgeArray(tdm);
+ const MLoop *mloop = tdm->getLoopArray(tdm);
+ unsigned int tnumedges = tdm->getNumEdges(tdm);
+ int adj_result;
+ SDefAdjacencyArray *vert_edges;
+ SDefAdjacency *adj_array;
+ SDefEdgePolys *edge_polys;
+
+ vert_edges = MEM_callocN(sizeof(*vert_edges) * tnumverts, "SDefVertEdgeMap");
+ if (vert_edges == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ return false;
+ }
+
+ adj_array = MEM_mallocN(sizeof(*adj_array) * tnumedges * 2, "SDefVertEdge");
+ if (adj_array == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ MEM_freeN(vert_edges);
+ return false;
+ }
+
+ edge_polys = MEM_callocN(sizeof(*edge_polys) * tnumedges, "SDefEdgeFaceMap");
+ if (edge_polys == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ MEM_freeN(vert_edges);
+ MEM_freeN(adj_array);
+ return false;
+ }
+
+ smd->verts = MEM_mallocN(sizeof(*smd->verts) * numverts, "SDefBindVerts");
+ if (smd->verts == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ return false;
+ }
+
+ bvhtree_from_mesh_looptri(&treeData, tdm, 0.0, 2, 6);
+ if (treeData.tree == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ MEM_freeN(smd->verts);
+ smd->verts = NULL;
+ return false;
+ }
+
+ adj_result = buildAdjacencyMap(mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys);
+
+ if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ free_bvhtree_from_mesh(&treeData);
+ MEM_freeN(smd->verts);
+ smd->verts = NULL;
+ return false;
+ }
+
+ smd->numverts = numverts;
+ smd->numpoly = tnumpoly;
+
+ SDefBindCalcData data = {.treeData = &treeData,
+ .vert_edges = vert_edges,
+ .edge_polys = edge_polys,
+ .mpoly = mpoly,
+ .medge = medge,
+ .mloop = mloop,
+ .looptri = tdm->getLoopTriArray(tdm),
+ .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetBindVertArray"),
+ .bind_verts = smd->verts,
+ .vertexCos = vertexCos,
+ .falloff = smd->falloff,
+ .success = MOD_SDEF_BIND_RESULT_SUCCESS};
+
+ if (data.targetCos == NULL) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeData((ModifierData *)smd);
+ return false;
+ }
+
+ invert_m4_m4(data.imat, smd->mat);
+
+ for (int i = 0; i < tnumverts; i++) {
+ mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
+ }
+
+ BLI_task_parallel_range_ex(0, numverts, &data, NULL, 0, bindVert,
+ numverts > 10000, false);
+
+ MEM_freeN(data.targetCos);
+
+ if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) {
+ modifier_setError((ModifierData *)smd, "Out of memory");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) {
+ modifier_setError((ModifierData *)smd, "Target has edges with more than two polygons");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) {
+ modifier_setError((ModifierData *)smd, "Target contains concave polygons");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) {
+ modifier_setError((ModifierData *)smd, "Target contains overlapping verts");
+ freeData((ModifierData *)smd);
+ }
+ else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) {
+ /* I know this message is vague, but I could not think of a way
+ * to explain this whith a reasonably sized message.
+ * Though it shouldn't really matter all that much,
+ * because this is very unlikely to occur */
+ modifier_setError((ModifierData *)smd, "Target contains invalid polygons");
+ freeData((ModifierData *)smd);
+ }
+
+ freeAdjacencyMap(vert_edges, adj_array, edge_polys);
+ free_bvhtree_from_mesh(&treeData);
+
+ return data.success == 1;
+}
+
+static void deformVert(void *userdata, void *UNUSED(userdata_chunk), const int index, const int UNUSED(threadid))
+{
+ const SDefDeformData * const data = (SDefDeformData *)userdata;
+ const SDefBind *sdbind = data->bind_verts[index].binds;
+ float * const vertexCos = data->vertexCos[index];
+ float norm[3], temp[3];
+
+ zero_v3(vertexCos);
+
+ for (int j = 0; j < data->bind_verts[index].numbinds; j++, sdbind++) {
+ /* Mode-generic operations (allocate poly coordinates) */
+ float (*coords)[3] = MEM_mallocN(sizeof(*coords) * sdbind->numverts, "SDefDoPolyCoords");
+
+ for (int k = 0; k < sdbind->numverts; k++) {
+ copy_v3_v3(coords[k], data->targetCos[sdbind->vert_inds[k]]);
+ }
+
+ normal_poly_v3(norm, coords, sdbind->numverts);
+ zero_v3(temp);
+
+ /* ---------- looptri mode ---------- */
+ if (sdbind->mode == MOD_SDEF_MODE_LOOPTRI) {
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[2]], sdbind->vert_weights[2]);
+ }
+ else {
+ /* ---------- ngon mode ---------- */
+ if (sdbind->mode == MOD_SDEF_MODE_NGON) {
+ for (int k = 0; k < sdbind->numverts; k++) {
+ madd_v3_v3fl(temp, coords[k], sdbind->vert_weights[k]);
+ }
+ }
+
+ /* ---------- centroid mode ---------- */
+ else if (sdbind->mode == MOD_SDEF_MODE_CENTROID) {
+ float cent[3];
+ mid_v3_v3_array(cent, coords, sdbind->numverts);
+
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[0]], sdbind->vert_weights[0]);
+ madd_v3_v3fl(temp, data->targetCos[sdbind->vert_inds[1]], sdbind->vert_weights[1]);
+ madd_v3_v3fl(temp, cent, sdbind->vert_weights[2]);
+ }
+ }
+
+ MEM_freeN(coords);
+
+ /* Apply normal offset (generic for all modes) */
+ madd_v3_v3fl(temp, norm, sdbind->normal_dist);
+
+ madd_v3_v3fl(vertexCos, temp, sdbind->influence);
+ }
+}
+
+static void surfacedeformModifier_do(ModifierData *md, float (*vertexCos)[3], unsigned int numverts, Object *ob)
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+ DerivedMesh *tdm;
+ unsigned int tnumverts, tnumpoly;
+
+ /* Exit function if bind flag is not set (free bind data if any) */
+ if (!(smd->flags & MOD_SDEF_BIND)) {
+ freeData(md);
+ return;
+ }
+
+ /* Handle target mesh both in and out of edit mode */
+ if (smd->target == md->scene->obedit) {
+ BMEditMesh *em = BKE_editmesh_from_object(smd->target);
+ tdm = em->derivedFinal;
+ }
+ else {
+ tdm = smd->target->derivedFinal;
+ }
+
+ tnumverts = tdm->getNumVerts(tdm);
+ tnumpoly = tdm->getNumPolys(tdm);
+
+ /* If not bound, execute bind */
+ if (!(smd->verts)) {
+ float tmp_mat[4][4];
+
+ invert_m4_m4(tmp_mat, ob->obmat);
+ mul_m4_m4m4(smd->mat, tmp_mat, smd->target->obmat);
+
+ if (!surfacedeformBind(smd, vertexCos, numverts, tnumpoly, tnumverts, tdm)) {
+ smd->flags &= ~MOD_SDEF_BIND;
+ return;
+ }
+ }
+
+ /* Poly count checks */
+ if (smd->numverts != numverts) {
+ modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts);
+ tdm->release(tdm);
+ return;
+ }
+ else if (smd->numpoly != tnumpoly) {
+ modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly);
+ tdm->release(tdm);
+ return;
+ }
+
+ /* Actual vertex location update starts here */
+ SDefDeformData data = {.bind_verts = smd->verts,
+ .targetCos = MEM_mallocN(sizeof(float[3]) * tnumverts, "SDefTargetVertArray"),
+ .vertexCos = vertexCos};
+
+ if (data.targetCos != NULL) {
+ bool tdm_vert_alloc;
+ const MVert * const mvert = DM_get_vert_array(tdm, &tdm_vert_alloc);
+
+ for (int i = 0; i < tnumverts; i++) {
+ mul_v3_m4v3(data.targetCos[i], smd->mat, mvert[i].co);
+ }
+
+ BLI_task_parallel_range_ex(0, numverts, &data, NULL, 0, deformVert,
+ numverts > 10000, false);
+
+ if (tdm_vert_alloc) {
+ MEM_freeN((void *)mvert);
+ }
+
+ MEM_freeN(data.targetCos);
+ }
+
+ tdm->release(tdm);
+}
+
+static void deformVerts(ModifierData *md, Object *ob,
+ DerivedMesh *UNUSED(derivedData),
+ float (*vertexCos)[3], int numVerts,
+ ModifierApplyFlag UNUSED(flag))
+{
+ surfacedeformModifier_do(md, vertexCos, numVerts, ob);
+}
+
+static void deformVertsEM(ModifierData *md, Object *ob,
+ struct BMEditMesh *UNUSED(editData),
+ DerivedMesh *UNUSED(derivedData),
+ float (*vertexCos)[3], int numVerts)
+{
+ surfacedeformModifier_do(md, vertexCos, numVerts, ob);
+}
+
+static bool isDisabled(ModifierData *md, int UNUSED(useRenderParams))
+{
+ SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
+
+ return !smd->target;
+}
+
+ModifierTypeInfo modifierType_SurfaceDeform = {
+ /* name */ "Surface Deform",
+ /* structName */ "SurfaceDeformModifierData",
+ /* structSize */ sizeof(SurfaceDeformModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ deformVertsEM,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ NULL,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ freeData,
+ /* isDisabled */ isDisabled,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 93414562ccf..ded1f0b77e6 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -287,5 +287,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(NormalEdit);
INIT_TYPE(CorrectiveSmooth);
INIT_TYPE(MeshSequenceCache);
+ INIT_TYPE(SurfaceDeform);
#undef INIT_TYPE
}
diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c
index 072267fc505..00ef6dd9733 100644
--- a/source/blender/modifiers/intern/MOD_uvwarp.c
+++ b/source/blender/modifiers/intern/MOD_uvwarp.c
@@ -225,7 +225,7 @@ static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk,
walk(userData, ob, &umd->object_src, IDWALK_CB_NOP);
}
-static void uv_warp_deps_object_bone(DagForest *forest, DagNode *obNode,
+static void UNUSED_FUNCTION(uv_warp_deps_object_bone)(DagForest *forest, DagNode *obNode,
Object *obj, const char *bonename)
{
if (obj) {
diff --git a/source/blender/nodes/composite/nodes/node_composite_glare.c b/source/blender/nodes/composite/nodes/node_composite_glare.c
index c512ea49586..76020e55463 100644
--- a/source/blender/nodes/composite/nodes/node_composite_glare.c
+++ b/source/blender/nodes/composite/nodes/node_composite_glare.c
@@ -50,7 +50,8 @@ static void node_composit_init_glare(bNodeTree *UNUSED(ntree), bNode *node)
ndg->colmod = 0.25;
ndg->mix = 0;
ndg->threshold = 1;
- ndg->angle = 4;
+ ndg->star_45 = true;
+ ndg->streaks = 4;
ndg->angle_ofs = 0.0f;
ndg->fade = 0.9;
ndg->size = 8;
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 40d1cfdfcb0..b5d77e99328 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -79,7 +79,8 @@ static void shader_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tre
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
if ((snode->shaderfrom == SNODE_SHADER_OBJECT) ||
(BKE_scene_use_new_shading_nodes(scene) == false))
diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h
index 4cb39e0f13b..79c58cb5715 100644
--- a/source/blender/nodes/shader/node_shader_util.h
+++ b/source/blender/nodes/shader/node_shader_util.h
@@ -76,6 +76,7 @@
#include "RE_pipeline.h"
#include "RE_shader_ext.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
diff --git a/source/blender/nodes/shader/nodes/node_shader_fresnel.c b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
index d5e11795fc0..5a9e33a4053 100644
--- a/source/blender/nodes/shader/nodes/node_shader_fresnel.c
+++ b/source/blender/nodes/shader/nodes/node_shader_fresnel.c
@@ -64,10 +64,11 @@ static void node_shader_exec_fresnel(void *data, int UNUSED(thread), bNode *UNUS
copy_v3_v3(n, shi->vn);
}
- if(shi->use_world_space_shading)
+ if (shi->use_world_space_shading) {
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
+ }
- out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1/eta : eta);
+ out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? 1 / eta : eta);
}
/* node type definition */
diff --git a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
index 90e2625b961..a0b2408a7bb 100644
--- a/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
+++ b/source/blender/nodes/shader/nodes/node_shader_layer_weight.c
@@ -69,7 +69,7 @@ static void node_shader_exec_layer_weight(void *data, int UNUSED(thread), bNode
if (shi->use_world_space_shading)
mul_mat3_m4_v3((float (*)[4])RE_render_current_get_matrix(RE_VIEW_MATRIX), n);
- out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1/eta);
+ out[0]->vec[0] = RE_fresnel_dielectric(shi->view, n, shi->flippednor ? eta : 1 / eta);
float facing = fabs(dot_v3v3(shi->view, n));
if (blend != 0.5) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
index 48d1688c386..e0bf34f42e4 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -63,7 +63,7 @@ static void node_shader_exec_normal_map(void *data, int UNUSED(thread), bNode *n
CLAMP_MIN(strength, 0.0f);
- float *N = shi->vno;
+ float *N = shi->nmapnorm;
int uv_index = 0;
switch (nm->space) {
case SHD_NORMAL_MAP_TANGENT:
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
index 0be47c4f751..1dfebc45d60 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_brick.c
@@ -64,7 +64,7 @@ static void node_shader_init_tex_brick(bNodeTree *UNUSED(ntree), bNode *node)
for (bNodeSocket *sock = node->inputs.first; sock; sock = sock->next) {
if (STREQ(sock->name, "Mortar Smooth")) {
- ((bNodeSocketValueFloat*)sock->default_value)->value = 0.1f;
+ ((bNodeSocketValueFloat *)sock->default_value)->value = 0.1f;
}
}
}
diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c
index 714665c303b..3b53d29d147 100644
--- a/source/blender/nodes/texture/node_texture_tree.c
+++ b/source/blender/nodes/texture/node_texture_tree.c
@@ -62,7 +62,8 @@ static void texture_get_from_context(const bContext *C, bNodeTreeType *UNUSED(tr
{
SpaceNode *snode = CTX_wm_space_node(C);
Scene *scene = CTX_data_scene(C);
- Object *ob = OBACT;
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ Object *ob = OBACT_NEW;
Tex *tx = NULL;
if (snode->texfrom == SNODE_TEX_OBJECT) {
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 359395b63c4..b694b6e994d 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -333,19 +333,14 @@ static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothMo
return 1;
}
-BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, float time)
+BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
{
Cloth *cloth = clmd->clothObject;
ClothSimSettings *parms = clmd->sim_parms;
Implicit_Data *data = cloth->implicit;
- ClothVertex *verts = cloth->verts;
bool no_compress = parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
- zero_v3(s->f);
- zero_m3(s->dfdx);
- zero_m3(s->dfdv);
-
s->flags &= ~CLOTH_SPRING_FLAG_NEEDED;
// calculate force of structural + shear springs
@@ -361,31 +356,13 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
// TODO: verify, half verified (couldn't see error)
// sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects
- BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, parms->max_sewing);
}
else {
- BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_linear(data, s->ij, s->kl, s->restlen, k, parms->Cdis, no_compress, 0.0f);
}
#endif
}
- else if (s->type & CLOTH_SPRING_TYPE_GOAL) {
-#ifdef CLOTH_FORCE_SPRING_GOAL
- float goal_x[3], goal_v[3];
- float k, scaling;
-
- s->flags |= CLOTH_SPRING_FLAG_NEEDED;
-
- // current_position = xold + t * (newposition - xold)
- /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
- interp_v3_v3v3(goal_x, verts[s->ij].xold, verts[s->ij].xconst, time / parms->time_scale);
- sub_v3_v3v3(goal_v, verts[s->ij].xconst, verts[s->ij].xold); // distance covered over dt==1
-
- scaling = parms->goalspring + s->stiffness * fabsf(parms->max_struct - parms->goalspring);
- k = verts[s->ij].goal * scaling / (parms->avg_spring_len + FLT_EPSILON);
-
- BPH_mass_spring_force_spring_goal(data, s->ij, goal_x, goal_v, k, parms->goalfrict * 0.01f, s->f, s->dfdx, s->dfdv);
-#endif
- }
else if (s->type & CLOTH_SPRING_TYPE_BENDING) { /* calculate force of bending springs */
#ifdef CLOTH_FORCE_SPRING_BEND
float kb, cb, scaling;
@@ -398,7 +375,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
// Fix for [#45084] for cloth stiffness must have cb proportional to kb
cb = kb * parms->bending_damping;
- BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb, s->f, s->dfdx, s->dfdv);
+ BPH_mass_spring_force_spring_bending(data, s->ij, s->kl, s->restlen, kb, cb);
#endif
}
else if (s->type & CLOTH_SPRING_TYPE_BENDING_ANG) {
@@ -474,9 +451,24 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
/* scale gravity force */
mul_v3_v3fl(gravity, clmd->scene->physics_settings.gravity, 0.001f * clmd->sim_parms->effector_weights->global_gravity);
}
+
vert = cloth->verts;
for (i = 0; i < cloth->mvert_num; i++, vert++) {
BPH_mass_spring_force_gravity(data, i, vert->mass, gravity);
+
+ /* Vertex goal springs */
+ if ((!(vert->flags & CLOTH_VERT_FLAG_PINNED)) && (vert->goal > FLT_EPSILON)) {
+ float goal_x[3], goal_v[3];
+ float k;
+
+ /* divide by time_scale to prevent goal vertices' delta locations from being multiplied */
+ interp_v3_v3v3(goal_x, vert->xold, vert->xconst, time / clmd->sim_parms->time_scale);
+ sub_v3_v3v3(goal_v, vert->xconst, vert->xold); /* distance covered over dt==1 */
+
+ k = vert->goal * clmd->sim_parms->goalspring / (clmd->sim_parms->avg_spring_len + FLT_EPSILON);
+
+ BPH_mass_spring_force_spring_goal(data, i, goal_x, goal_v, k, clmd->sim_parms->goalfrict * 0.01f);
+ }
}
#endif
@@ -544,8 +536,9 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), ListB
for (LinkNode *link = cloth->springs; link; link = link->next) {
ClothSpring *spring = (ClothSpring *)link->link;
// only handle active springs
- if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE))
- cloth_calc_spring_force(clmd, spring, time);
+ if (!(spring->flags & CLOTH_SPRING_FLAG_DEACTIVATE)) {
+ cloth_calc_spring_force(clmd, spring);
+ }
}
}
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index d1a75ca5297..2f62ab98e12 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -114,19 +114,15 @@ void BPH_mass_spring_force_edge_wind(struct Implicit_Data *data, int v1, int v2,
void BPH_mass_spring_force_vertex_wind(struct Implicit_Data *data, int v, float radius, const float (*winvec)[3]);
/* Linear spring force between two points */
bool BPH_mass_spring_force_spring_linear(struct Implicit_Data *data, int i, int j, float restlen,
- float stiffness, float damping, bool no_compress, float clamp_force,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+ float stiffness, float damping, bool no_compress, float clamp_force);
/* Bending force, forming a triangle at the base of two structural springs */
-bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen,
- float kb, float cb,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+bool BPH_mass_spring_force_spring_bending(struct Implicit_Data *data, int i, int j, float restlen, float kb, float cb);
/* Angular bending force based on local target vectors */
bool BPH_mass_spring_force_spring_bending_angular(struct Implicit_Data *data, int i, int j, int k,
const float target[3], float stiffness, float damping);
/* Global goal spring */
bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
- float stiffness, float damping,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3]);
+ float stiffness, float damping);
/* ======== Hair Volumetric Forces ======== */
diff --git a/source/blender/physics/intern/implicit_blender.c b/source/blender/physics/intern/implicit_blender.c
index 2ad8ee0547f..16cd335dc0c 100644
--- a/source/blender/physics/intern/implicit_blender.c
+++ b/source/blender/physics/intern/implicit_blender.c
@@ -1579,8 +1579,7 @@ BLI_INLINE void apply_spring(Implicit_Data *data, int i, int j, const float f[3]
}
bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, float restlen,
- float stiffness, float damping, bool no_compress, float clamp_force,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+ float stiffness, float damping, bool no_compress, float clamp_force)
{
float extent[3], length, dir[3], vel[3];
@@ -1608,25 +1607,15 @@ bool BPH_mass_spring_force_spring_linear(Implicit_Data *data, int i, int j, floa
apply_spring(data, i, j, f, dfdx, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
/* See "Stable but Responsive Cloth" (Choi, Ko 2005) */
-bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen,
- float kb, float cb,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, float restlen, float kb, float cb)
{
float extent[3], length, dir[3], vel[3];
@@ -1646,17 +1635,9 @@ bool BPH_mass_spring_force_spring_bending(Implicit_Data *data, int i, int j, flo
apply_spring(data, i, j, f, dfdx, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
@@ -1945,8 +1926,7 @@ bool BPH_mass_spring_force_spring_bending_angular(Implicit_Data *data, int i, in
}
bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float goal_x[3], const float goal_v[3],
- float stiffness, float damping,
- float r_f[3], float r_dfdx[3][3], float r_dfdv[3][3])
+ float stiffness, float damping)
{
float root_goal_x[3], root_goal_v[3], extent[3], length, dir[3], vel[3];
float f[3], dfdx[3][3], dfdv[3][3];
@@ -1973,17 +1953,9 @@ bool BPH_mass_spring_force_spring_goal(Implicit_Data *data, int i, const float g
add_m3_m3m3(data->dFdX[i].m, data->dFdX[i].m, dfdx);
add_m3_m3m3(data->dFdV[i].m, data->dFdV[i].m, dfdv);
- if (r_f) copy_v3_v3(r_f, f);
- if (r_dfdx) copy_m3_m3(r_dfdx, dfdx);
- if (r_dfdv) copy_m3_m3(r_dfdv, dfdv);
-
return true;
}
else {
- if (r_f) zero_v3(r_f);
- if (r_dfdx) zero_m3(r_dfdx);
- if (r_dfdv) zero_m3(r_dfdv);
-
return false;
}
}
diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h
index 3148dab3c50..b4c36a7c516 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -75,7 +75,8 @@ void BPY_thread_restore(BPy_ThreadStatePtr tstate);
bool BPY_execute_filepath(struct bContext *C, const char *filepath, struct ReportList *reports);
bool BPY_execute_text(struct bContext *C, struct Text *text, struct ReportList *reports, const bool do_jump);
-bool BPY_execute_string_as_number(struct bContext *C, const char *expr, double *value, const bool verbose);
+bool BPY_execute_string_as_number(struct bContext *C, const char *expr, const bool verbose, double *r_value);
+bool BPY_execute_string_as_string(struct bContext *C, const char *expr, const bool verbose, char **r_value);
bool BPY_execute_string_ex(struct bContext *C, const char *expr, bool use_eval);
bool BPY_execute_string(struct bContext *C, const char *expr);
diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c
index 1fc575480dc..63fc00f0a43 100644
--- a/source/blender/python/generic/bgl.c
+++ b/source/blender/python/generic/bgl.c
@@ -185,11 +185,13 @@
#define GLbitfield_ref(num) &bgl_var##num
#define GLbitfield_def(num) /* unsigned */ int GLbitfield_var(num)
+#if 0
/* typedef signed char GLbyte; */
#define GLbyte_str "b"
#define GLbyte_var(num) bgl_var##num
#define GLbyte_ref(num) &bgl_var##num
#define GLbyte_def(num) signed char GLbyte_var(num)
+#endif
/* typedef short GLshort; */
#define GLshort_str "h"
@@ -227,11 +229,13 @@
#define GLubyte_ref(num) &bgl_var##num
#define GLubyte_def(num) /* unsigned */ char GLubyte_var(num)
+#if 0
/* typedef unsigned short GLushort; */
#define GLushort_str "H"
#define GLushort_var(num) bgl_var##num
#define GLushort_ref(num) &bgl_var##num
#define GLushort_def(num) /* unsigned */ short GLushort_var(num)
+#endif
/* typedef unsigned int GLuint; */
#define GLuint_str "I"
@@ -1015,358 +1019,71 @@ static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
ret_ret_##ret; \
}
-#define BGLU_Wrap(funcname, ret, arg_list) \
-static PyObject *Method_##funcname (PyObject *UNUSED(self), PyObject *args) \
-{ \
- arg_def arg_list; \
- ret_def_##ret; \
- if (!PyArg_ParseTuple(args, arg_str arg_list, arg_ref arg_list)) { \
- return NULL; \
- } \
- ret_set_##ret glu##funcname (arg_var arg_list); \
- ret_ret_##ret; \
-}
-
/* GL_VERSION_1_0 */
-BGL_Wrap(Accum, void, (GLenum, GLfloat))
-BGL_Wrap(AlphaFunc, void, (GLenum, GLfloat))
-BGL_Wrap(Begin, void, (GLenum))
-BGL_Wrap(Bitmap, void, (GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, GLubyteP))
BGL_Wrap(BlendFunc, void, (GLenum, GLenum))
-BGL_Wrap(CallList, void, (GLuint))
-BGL_Wrap(CallLists, void, (GLsizei, GLenum, GLvoidP))
BGL_Wrap(Clear, void, (GLbitfield))
-BGL_Wrap(ClearAccum, void, (GLfloat, GLfloat, GLfloat, GLfloat))
BGL_Wrap(ClearColor, void, (GLfloat, GLfloat, GLfloat, GLfloat))
BGL_Wrap(ClearDepth, void, (GLdouble))
-BGL_Wrap(ClearIndex, void, (GLfloat))
BGL_Wrap(ClearStencil, void, (GLint))
-BGL_Wrap(ClipPlane, void, (GLenum, GLdoubleP))
-BGL_Wrap(Color3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color3bv, void, (GLbyteP))
-BGL_Wrap(Color3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color3dv, void, (GLdoubleP))
-BGL_Wrap(Color3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color3fv, void, (GLfloatP))
-BGL_Wrap(Color3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Color3iv, void, (GLintP))
-BGL_Wrap(Color3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Color3sv, void, (GLshortP))
-BGL_Wrap(Color3ub, void, (GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color3ubv, void, (GLubyteP))
-BGL_Wrap(Color3ui, void, (GLuint, GLuint, GLuint))
-BGL_Wrap(Color3uiv, void, (GLuintP))
-BGL_Wrap(Color3us, void, (GLushort, GLushort, GLushort))
-BGL_Wrap(Color3usv, void, (GLushortP))
-BGL_Wrap(Color4b, void, (GLbyte, GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Color4bv, void, (GLbyteP))
-BGL_Wrap(Color4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Color4dv, void, (GLdoubleP))
-BGL_Wrap(Color4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Color4fv, void, (GLfloatP))
-BGL_Wrap(Color4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Color4iv, void, (GLintP))
-BGL_Wrap(Color4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Color4sv, void, (GLshortP))
-BGL_Wrap(Color4ub, void, (GLubyte, GLubyte, GLubyte, GLubyte))
-BGL_Wrap(Color4ubv, void, (GLubyteP))
-BGL_Wrap(Color4ui, void, (GLuint, GLuint, GLuint, GLuint))
-BGL_Wrap(Color4uiv, void, (GLuintP))
-BGL_Wrap(Color4us, void, (GLushort, GLushort, GLushort, GLushort))
-BGL_Wrap(Color4usv, void, (GLushortP))
BGL_Wrap(ColorMask, void, (GLboolean, GLboolean, GLboolean, GLboolean))
-BGL_Wrap(ColorMaterial, void, (GLenum, GLenum))
-BGL_Wrap(CopyPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum))
BGL_Wrap(CullFace, void, (GLenum))
-BGL_Wrap(DeleteLists, void, (GLuint, GLsizei))
BGL_Wrap(DepthFunc, void, (GLenum))
BGL_Wrap(DepthMask, void, (GLboolean))
BGL_Wrap(DepthRange, void, (GLdouble, GLdouble))
BGL_Wrap(Disable, void, (GLenum))
BGL_Wrap(DrawBuffer, void, (GLenum))
-BGL_Wrap(DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlag, void, (GLboolean))
-BGL_Wrap(EdgeFlagv, void, (GLbooleanP))
BGL_Wrap(Enable, void, (GLenum))
-BGL_Wrap(End, void, (void))
-BGL_Wrap(EndList, void, (void))
-BGL_Wrap(EvalCoord1d, void, (GLdouble))
-BGL_Wrap(EvalCoord1dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord1f, void, (GLfloat))
-BGL_Wrap(EvalCoord1fv, void, (GLfloatP))
-BGL_Wrap(EvalCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(EvalCoord2dv, void, (GLdoubleP))
-BGL_Wrap(EvalCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(EvalCoord2fv, void, (GLfloatP))
-BGL_Wrap(EvalMesh1, void, (GLenum, GLint, GLint))
-BGL_Wrap(EvalMesh2, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(EvalPoint1, void, (GLint))
-BGL_Wrap(EvalPoint2, void, (GLint, GLint))
-BGL_Wrap(FeedbackBuffer, void, (GLsizei, GLenum, GLfloatP))
BGL_Wrap(Finish, void, (void))
BGL_Wrap(Flush, void, (void))
-BGL_Wrap(Fogf, void, (GLenum, GLfloat))
-BGL_Wrap(Fogfv, void, (GLenum, GLfloatP))
-BGL_Wrap(Fogi, void, (GLenum, GLint))
-BGL_Wrap(Fogiv, void, (GLenum, GLintP))
BGL_Wrap(FrontFace, void, (GLenum))
-BGL_Wrap(Frustum, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(GenLists, GLuint, (GLsizei))
BGL_Wrap(GetBooleanv, void, (GLenum, GLbooleanP))
-BGL_Wrap(GetClipPlane, void, (GLenum, GLdoubleP))
BGL_Wrap(GetDoublev, void, (GLenum, GLdoubleP))
BGL_Wrap(GetError, GLenum, (void))
BGL_Wrap(GetFloatv, void, (GLenum, GLfloatP))
BGL_Wrap(GetIntegerv, void, (GLenum, GLintP))
-BGL_Wrap(GetLightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetLightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMapdv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetMapfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMapiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetMaterialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetMaterialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetPixelMapfv, void, (GLenum, GLfloatP))
-BGL_Wrap(GetPixelMapuiv, void, (GLenum, GLuintP))
-BGL_Wrap(GetPixelMapusv, void, (GLenum, GLushortP))
-BGL_Wrap(GetPolygonStipple, void, (GLubyteP))
BGL_Wrap(GetString, GLstring, (GLenum))
-BGL_Wrap(GetTexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(GetTexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(GetTexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(GetTexGeniv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(GetTexImage, void, (GLenum, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(GetTexLevelParameterfv, void, (GLenum, GLint, GLenum, GLfloatP))
BGL_Wrap(GetTexLevelParameteriv, void, (GLenum, GLint, GLenum, GLintP))
BGL_Wrap(GetTexParameterfv, void, (GLenum, GLenum, GLfloatP))
BGL_Wrap(GetTexParameteriv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(Hint, void, (GLenum, GLenum))
-BGL_Wrap(IndexMask, void, (GLuint))
-BGL_Wrap(Indexd, void, (GLdouble))
-BGL_Wrap(Indexdv, void, (GLdoubleP))
-BGL_Wrap(Indexf, void, (GLfloat))
-BGL_Wrap(Indexfv, void, (GLfloatP))
-BGL_Wrap(Indexi, void, (GLint))
-BGL_Wrap(Indexiv, void, (GLintP))
-BGL_Wrap(Indexs, void, (GLshort))
-BGL_Wrap(Indexsv, void, (GLshortP))
-BGL_Wrap(InitNames, void, (void))
BGL_Wrap(IsEnabled, GLboolean, (GLenum))
-BGL_Wrap(IsList, GLboolean, (GLuint))
-BGL_Wrap(LightModelf, void, (GLenum, GLfloat))
-BGL_Wrap(LightModelfv, void, (GLenum, GLfloatP))
-BGL_Wrap(LightModeli, void, (GLenum, GLint))
-BGL_Wrap(LightModeliv, void, (GLenum, GLintP))
-BGL_Wrap(Lightf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Lightfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Lighti, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Lightiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(LineStipple, void, (GLint, GLushort))
BGL_Wrap(LineWidth, void, (GLfloat))
-BGL_Wrap(ListBase, void, (GLuint))
-BGL_Wrap(LoadIdentity, void, (void))
-BGL_Wrap(LoadMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadMatrixf, void, (GLfloatP))
-BGL_Wrap(LoadName, void, (GLuint))
BGL_Wrap(LogicOp, void, (GLenum))
-BGL_Wrap(Map1d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map1f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(Map2d, void, (GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, GLdoubleP))
-BGL_Wrap(Map2f, void, (GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, GLfloatP))
-BGL_Wrap(MapGrid1d, void, (GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid1f, void, (GLint, GLfloat, GLfloat))
-BGL_Wrap(MapGrid2d, void, (GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble))
-BGL_Wrap(MapGrid2f, void, (GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat))
-BGL_Wrap(Materialf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(Materialfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(Materiali, void, (GLenum, GLenum, GLint))
-BGL_Wrap(Materialiv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(MatrixMode, void, (GLenum))
-BGL_Wrap(MultMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultMatrixf, void, (GLfloatP))
-BGL_Wrap(NewList, void, (GLuint, GLenum))
-BGL_Wrap(Normal3b, void, (GLbyte, GLbyte, GLbyte))
-BGL_Wrap(Normal3bv, void, (GLbyteP))
-BGL_Wrap(Normal3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Normal3dv, void, (GLdoubleP))
-BGL_Wrap(Normal3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Normal3fv, void, (GLfloatP))
-BGL_Wrap(Normal3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Normal3iv, void, (GLintP))
-BGL_Wrap(Normal3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Normal3sv, void, (GLshortP))
-BGL_Wrap(Ortho, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(PassThrough, void, (GLfloat))
-BGL_Wrap(PixelMapfv, void, (GLenum, GLsizei, GLfloatP))
-BGL_Wrap(PixelMapuiv, void, (GLenum, GLsizei, GLuintP))
-BGL_Wrap(PixelMapusv, void, (GLenum, GLsizei, GLushortP))
BGL_Wrap(PixelStoref, void, (GLenum, GLfloat))
BGL_Wrap(PixelStorei, void, (GLenum, GLint))
-BGL_Wrap(PixelTransferf, void, (GLenum, GLfloat))
-BGL_Wrap(PixelTransferi, void, (GLenum, GLint))
-BGL_Wrap(PixelZoom, void, (GLfloat, GLfloat))
BGL_Wrap(PointSize, void, (GLfloat))
BGL_Wrap(PolygonMode, void, (GLenum, GLenum))
-BGL_Wrap(PolygonStipple, void, (GLubyteP))
-BGL_Wrap(PopAttrib, void, (void))
-BGL_Wrap(PopMatrix, void, (void))
-BGL_Wrap(PopName, void, (void))
-BGL_Wrap(PushAttrib, void, (GLbitfield))
-BGL_Wrap(PushMatrix, void, (void))
-BGL_Wrap(PushName, void, (GLuint))
-BGL_Wrap(RasterPos2d, void, (GLdouble, GLdouble))
-BGL_Wrap(RasterPos2dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos2f, void, (GLfloat, GLfloat))
-BGL_Wrap(RasterPos2fv, void, (GLfloatP))
-BGL_Wrap(RasterPos2i, void, (GLint, GLint))
-BGL_Wrap(RasterPos2iv, void, (GLintP))
-BGL_Wrap(RasterPos2s, void, (GLshort, GLshort))
-BGL_Wrap(RasterPos2sv, void, (GLshortP))
-BGL_Wrap(RasterPos3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos3dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos3fv, void, (GLfloatP))
-BGL_Wrap(RasterPos3i, void, (GLint, GLint, GLint))
-BGL_Wrap(RasterPos3iv, void, (GLintP))
-BGL_Wrap(RasterPos3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos3sv, void, (GLshortP))
-BGL_Wrap(RasterPos4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(RasterPos4dv, void, (GLdoubleP))
-BGL_Wrap(RasterPos4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(RasterPos4fv, void, (GLfloatP))
-BGL_Wrap(RasterPos4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(RasterPos4iv, void, (GLintP))
-BGL_Wrap(RasterPos4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(RasterPos4sv, void, (GLshortP))
BGL_Wrap(ReadBuffer, void, (GLenum))
BGL_Wrap(ReadPixels, void, (GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(Rectd, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rectdv, void, (GLdoubleP, GLdoubleP))
-BGL_Wrap(Rectf, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Rectfv, void, (GLfloatP, GLfloatP))
-BGL_Wrap(Recti, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Rectiv, void, (GLintP, GLintP))
-BGL_Wrap(Rects, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Rectsv, void, (GLshortP, GLshortP))
-BGL_Wrap(RenderMode, GLint, (GLenum))
-BGL_Wrap(Rotated, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Rotatef, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Scaled, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Scalef, void, (GLfloat, GLfloat, GLfloat))
BGL_Wrap(Scissor, void, (GLint, GLint, GLsizei, GLsizei))
-BGL_Wrap(SelectBuffer, void, (GLsizei, GLuintP))
-BGL_Wrap(ShadeModel, void, (GLenum))
BGL_Wrap(StencilFunc, void, (GLenum, GLint, GLuint))
BGL_Wrap(StencilMask, void, (GLuint))
BGL_Wrap(StencilOp, void, (GLenum, GLenum, GLenum))
-BGL_Wrap(TexCoord1d, void, (GLdouble))
-BGL_Wrap(TexCoord1dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord1f, void, (GLfloat))
-BGL_Wrap(TexCoord1fv, void, (GLfloatP))
-BGL_Wrap(TexCoord1i, void, (GLint))
-BGL_Wrap(TexCoord1iv, void, (GLintP))
-BGL_Wrap(TexCoord1s, void, (GLshort))
-BGL_Wrap(TexCoord1sv, void, (GLshortP))
-BGL_Wrap(TexCoord2d, void, (GLdouble, GLdouble))
-BGL_Wrap(TexCoord2dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord2f, void, (GLfloat, GLfloat))
-BGL_Wrap(TexCoord2fv, void, (GLfloatP))
-BGL_Wrap(TexCoord2i, void, (GLint, GLint))
-BGL_Wrap(TexCoord2iv, void, (GLintP))
-BGL_Wrap(TexCoord2s, void, (GLshort, GLshort))
-BGL_Wrap(TexCoord2sv, void, (GLshortP))
-BGL_Wrap(TexCoord3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord3dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord3fv, void, (GLfloatP))
-BGL_Wrap(TexCoord3i, void, (GLint, GLint, GLint))
-BGL_Wrap(TexCoord3iv, void, (GLintP))
-BGL_Wrap(TexCoord3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord3sv, void, (GLshortP))
-BGL_Wrap(TexCoord4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(TexCoord4dv, void, (GLdoubleP))
-BGL_Wrap(TexCoord4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(TexCoord4fv, void, (GLfloatP))
-BGL_Wrap(TexCoord4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(TexCoord4iv, void, (GLintP))
-BGL_Wrap(TexCoord4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(TexCoord4sv, void, (GLshortP))
-BGL_Wrap(TexEnvf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexEnvfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexEnvi, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexEnviv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(TexGend, void, (GLenum, GLenum, GLdouble))
-BGL_Wrap(TexGendv, void, (GLenum, GLenum, GLdoubleP))
-BGL_Wrap(TexGenf, void, (GLenum, GLenum, GLfloat))
-BGL_Wrap(TexGenfv, void, (GLenum, GLenum, GLfloatP))
-BGL_Wrap(TexGeni, void, (GLenum, GLenum, GLint))
-BGL_Wrap(TexGeniv, void, (GLenum, GLenum, GLintP))
BGL_Wrap(TexImage1D, void, (GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexImage2D, void, (GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexParameterf, void, (GLenum, GLenum, GLfloat))
BGL_Wrap(TexParameterfv, void, (GLenum, GLenum, GLfloatP))
BGL_Wrap(TexParameteri, void, (GLenum, GLenum, GLint))
BGL_Wrap(TexParameteriv, void, (GLenum, GLenum, GLintP))
-BGL_Wrap(Translated, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Translatef, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex2d, void, (GLdouble, GLdouble))
-BGL_Wrap(Vertex2dv, void, (GLdoubleP))
-BGL_Wrap(Vertex2f, void, (GLfloat, GLfloat))
-BGL_Wrap(Vertex2fv, void, (GLfloatP))
-BGL_Wrap(Vertex2i, void, (GLint, GLint))
-BGL_Wrap(Vertex2iv, void, (GLintP))
-BGL_Wrap(Vertex2s, void, (GLshort, GLshort))
-BGL_Wrap(Vertex2sv, void, (GLshortP))
-BGL_Wrap(Vertex3d, void, (GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex3dv, void, (GLdoubleP))
-BGL_Wrap(Vertex3f, void, (GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex3fv, void, (GLfloatP))
-BGL_Wrap(Vertex3i, void, (GLint, GLint, GLint))
-BGL_Wrap(Vertex3iv, void, (GLintP))
-BGL_Wrap(Vertex3s, void, (GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex3sv, void, (GLshortP))
-BGL_Wrap(Vertex4d, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(Vertex4dv, void, (GLdoubleP))
-BGL_Wrap(Vertex4f, void, (GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(Vertex4fv, void, (GLfloatP))
-BGL_Wrap(Vertex4i, void, (GLint, GLint, GLint, GLint))
-BGL_Wrap(Vertex4iv, void, (GLintP))
-BGL_Wrap(Vertex4s, void, (GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(Vertex4sv, void, (GLshortP))
BGL_Wrap(Viewport, void, (GLint, GLint, GLsizei, GLsizei))
/* GL_VERSION_1_1 */
-BGL_Wrap(AreTexturesResident, GLboolean, (GLsizei, GLuintP, GLbooleanP))
-BGL_Wrap(ArrayElement, void, (GLint))
BGL_Wrap(BindTexture, void, (GLenum, GLuint))
-BGL_Wrap(ColorPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
BGL_Wrap(CopyTexImage1D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint))
BGL_Wrap(CopyTexImage2D, void, (GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint))
BGL_Wrap(CopyTexSubImage1D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei))
BGL_Wrap(CopyTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei))
BGL_Wrap(DeleteTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(DisableClientState, void, (GLenum))
BGL_Wrap(DrawArrays, void, (GLenum, GLint, GLsizei))
BGL_Wrap(DrawElements, void, (GLenum, GLsizei, GLenum, GLvoidP))
-BGL_Wrap(EdgeFlagPointer, void, (GLsizei, GLvoidP))
-BGL_Wrap(EnableClientState, void, (GLenum))
BGL_Wrap(GenTextures, void, (GLsizei, GLuintP))
-BGL_Wrap(GetPointerv, void, (GLenum, GLvoidP))
-BGL_Wrap(IndexPointer, void, (GLenum, GLsizei, GLvoidP))
-BGL_Wrap(Indexub, void, (GLubyte))
-BGL_Wrap(Indexubv, void, (GLubyteP))
-BGL_Wrap(InterleavedArrays, void, (GLenum, GLsizei, GLvoidP))
BGL_Wrap(IsTexture, GLboolean, (GLuint))
-BGL_Wrap(NormalPointer, void, (GLenum, GLsizei, GLvoidP))
BGL_Wrap(PolygonOffset, void, (GLfloat, GLfloat))
-BGL_Wrap(PopClientAttrib, void, (void))
-BGL_Wrap(PrioritizeTextures, void, (GLsizei, GLuintP, GLfloatP))
-BGL_Wrap(PushClientAttrib, void, (GLbitfield))
-BGL_Wrap(TexCoordPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
BGL_Wrap(TexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, GLenum, GLenum, GLvoidP))
BGL_Wrap(TexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
-BGL_Wrap(VertexPointer, void, (GLint, GLenum, GLsizei, GLvoidP))
/* GL_VERSION_1_2 */
@@ -1378,7 +1095,6 @@ BGL_Wrap(TexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLi
/* GL_VERSION_1_3 */
BGL_Wrap(ActiveTexture, void, (GLenum))
-BGL_Wrap(ClientActiveTexture, void, (GLenum))
BGL_Wrap(CompressedTexImage1D, void, (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexImage2D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexImage3D, void, (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, GLvoidP))
@@ -1386,42 +1102,6 @@ BGL_Wrap(CompressedTexSubImage1D, void, (GLenum, GLint, GLint, GLsizei, G
BGL_Wrap(CompressedTexSubImage2D, void, (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
BGL_Wrap(CompressedTexSubImage3D, void, (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, GLvoidP))
BGL_Wrap(GetCompressedTexImage, void, (GLenum, GLint, GLvoidP))
-BGL_Wrap(LoadTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(LoadTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultTransposeMatrixd, void, (GLdoubleP))
-BGL_Wrap(MultTransposeMatrixf, void, (GLfloatP))
-BGL_Wrap(MultiTexCoord1d, void, (GLenum, GLdouble))
-BGL_Wrap(MultiTexCoord1dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord1f, void, (GLenum, GLfloat))
-BGL_Wrap(MultiTexCoord1fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord1i, void, (GLenum, GLint))
-BGL_Wrap(MultiTexCoord1iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord1s, void, (GLenum, GLshort))
-BGL_Wrap(MultiTexCoord1sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord2d, void, (GLenum, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord2dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord2f, void, (GLenum, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord2fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord2i, void, (GLenum, GLint, GLint))
-BGL_Wrap(MultiTexCoord2iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord2s, void, (GLenum, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord2sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord3d, void, (GLenum, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord3dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord3f, void, (GLenum, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord3fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord3i, void, (GLenum, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord3iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord3s, void, (GLenum, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord3sv, void, (GLenum, GLshortP))
-BGL_Wrap(MultiTexCoord4d, void, (GLenum, GLdouble, GLdouble, GLdouble, GLdouble))
-BGL_Wrap(MultiTexCoord4dv, void, (GLenum, GLdoubleP))
-BGL_Wrap(MultiTexCoord4f, void, (GLenum, GLfloat, GLfloat, GLfloat, GLfloat))
-BGL_Wrap(MultiTexCoord4fv, void, (GLenum, GLfloatP))
-BGL_Wrap(MultiTexCoord4i, void, (GLenum, GLint, GLint, GLint, GLint))
-BGL_Wrap(MultiTexCoord4iv, void, (GLenum, GLintP))
-BGL_Wrap(MultiTexCoord4s, void, (GLenum, GLshort, GLshort, GLshort, GLshort))
-BGL_Wrap(MultiTexCoord4sv, void, (GLenum, GLshortP))
BGL_Wrap(SampleCoverage, void, (GLfloat, GLboolean))
@@ -1587,44 +1267,7 @@ BGL_Wrap(TexImage3DMultisample, void, (GLenum, GLsizei, GLenum, GLsizei
/* GL_VERSION_3_3 */
-BGL_Wrap(ColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(ColorP4ui, void, (GLenum, GLuint))
-BGL_Wrap(ColorP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP1ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP1uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP2ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP2uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP3ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP3uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(MultiTexCoordP4ui, void, (GLenum, GLenum, GLuint))
-BGL_Wrap(MultiTexCoordP4uiv, void, (GLenum, GLenum, GLuintP))
-BGL_Wrap(NormalP3ui, void, (GLenum, GLuint))
-BGL_Wrap(NormalP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(SecondaryColorP3ui, void, (GLenum, GLuint))
-BGL_Wrap(SecondaryColorP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP1ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP1uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP2ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP3ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(TexCoordP4ui, void, (GLenum, GLuint))
-BGL_Wrap(TexCoordP4uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP2ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP2uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP3ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP3uiv, void, (GLenum, GLuintP))
-BGL_Wrap(VertexP4ui, void, (GLenum, GLuint))
-BGL_Wrap(VertexP4uiv, void, (GLenum, GLuintP))
-
-
-BGLU_Wrap(Perspective, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(LookAt, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(Ortho2D, void, (GLdouble, GLdouble, GLdouble, GLdouble))
-BGLU_Wrap(PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdouble, GLintP))
-BGLU_Wrap(Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
-BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
+/* no new functions besides packed immediate mode (not part of core profile) */
/** \} */
@@ -1634,26 +1277,12 @@ BGLU_Wrap(UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdouble
/** \name Module Definition
* \{ */
-#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, NULL}
-
-static struct PyMethodDef BGL_methods[] = {
- MethodDefu(Perspective),
- MethodDefu(LookAt),
- MethodDefu(Ortho2D),
- MethodDefu(PickMatrix),
- MethodDefu(Project),
- MethodDefu(UnProject),
- {NULL, NULL, 0, NULL}
-};
-
-#undef MethodDefu
-
static struct PyModuleDef BGL_module_def = {
PyModuleDef_HEAD_INIT,
"bgl", /* m_name */
NULL, /* m_doc */
0, /* m_size */
- BGL_methods, /* m_methods */
+ NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
@@ -1971,36 +1600,6 @@ PyObject *BPyInit_bgl(void)
/* GL_VERSION_3_3 */
{
- PY_MOD_ADD_METHOD(ColorP3ui);
- PY_MOD_ADD_METHOD(ColorP3uiv);
- PY_MOD_ADD_METHOD(ColorP4ui);
- PY_MOD_ADD_METHOD(ColorP4uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP1ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP1uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP2ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP2uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP3ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP3uiv);
- PY_MOD_ADD_METHOD(MultiTexCoordP4ui);
- PY_MOD_ADD_METHOD(MultiTexCoordP4uiv);
- PY_MOD_ADD_METHOD(NormalP3ui);
- PY_MOD_ADD_METHOD(NormalP3uiv);
- PY_MOD_ADD_METHOD(SecondaryColorP3ui);
- PY_MOD_ADD_METHOD(SecondaryColorP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP1ui);
- PY_MOD_ADD_METHOD(TexCoordP1uiv);
- PY_MOD_ADD_METHOD(TexCoordP2ui);
- PY_MOD_ADD_METHOD(TexCoordP2uiv);
- PY_MOD_ADD_METHOD(TexCoordP3ui);
- PY_MOD_ADD_METHOD(TexCoordP3uiv);
- PY_MOD_ADD_METHOD(TexCoordP4ui);
- PY_MOD_ADD_METHOD(TexCoordP4uiv);
- PY_MOD_ADD_METHOD(VertexP2ui);
- PY_MOD_ADD_METHOD(VertexP2uiv);
- PY_MOD_ADD_METHOD(VertexP3ui);
- PY_MOD_ADD_METHOD(VertexP3uiv);
- PY_MOD_ADD_METHOD(VertexP4ui);
- PY_MOD_ADD_METHOD(VertexP4uiv);
}
#define PY_DICT_ADD_INT(x) py_module_dict_add_int(dict, #x, x)
diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c
index 7b2d58a1268..2e789d6d4b3 100644
--- a/source/blender/python/generic/py_capi_utils.c
+++ b/source/blender/python/generic/py_capi_utils.c
@@ -918,11 +918,11 @@ char *PyC_FlagSet_AsString(PyC_FlagSet *item)
return cstring;
}
-int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value)
+int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value)
{
for ( ; item->identifier; item++) {
if (STREQ(item->identifier, identifier)) {
- *value = item->value;
+ *r_value = item->value;
return 1;
}
}
@@ -930,9 +930,9 @@ int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *
return 0;
}
-int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix)
+int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix)
{
- if (PyC_FlagSet_ValueFromID_int(item, identifier, value) == 0) {
+ if (PyC_FlagSet_ValueFromID_int(item, identifier, r_value) == 0) {
const char *enum_str = PyC_FlagSet_AsString(item);
PyErr_Format(PyExc_ValueError,
"%s: '%.200s' not found in (%s)",
@@ -1006,7 +1006,7 @@ PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag)
*
* \note it is caller's responsibility to acquire & release GIL!
*/
-bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename)
+bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value)
{
PyObject *py_dict, *mod, *retval;
bool ok = true;
@@ -1058,10 +1058,10 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam
ok = false;
}
else if (!isfinite(val)) {
- *value = 0.0;
+ *r_value = 0.0;
}
else {
- *value = val;
+ *r_value = val;
}
}
@@ -1070,4 +1070,41 @@ bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filenam
return ok;
}
+bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value)
+{
+ PyObject *py_dict, *retval;
+ bool ok = true;
+ PyObject *main_mod = NULL;
+
+ PyC_MainModule_Backup(&main_mod);
+
+ py_dict = PyC_DefaultNameSpace(filename);
+
+ retval = PyRun_String(expr, Py_eval_input, py_dict, py_dict);
+
+ if (retval == NULL) {
+ ok = false;
+ }
+ else {
+ const char *val;
+ Py_ssize_t val_len;
+
+ val = _PyUnicode_AsStringAndSize(retval, &val_len);
+ if (val == NULL && PyErr_Occurred()) {
+ ok = false;
+ }
+ else {
+ char *val_alloc = MEM_mallocN(val_len + 1, __func__);
+ memcpy(val_alloc, val, val_len + 1);
+ *r_value = val_alloc;
+ }
+
+ Py_DECREF(retval);
+ }
+
+ PyC_MainModule_Restore(main_mod);
+
+ return ok;
+}
+
#endif /* #ifndef MATH_STANDALONE */
diff --git a/source/blender/python/generic/py_capi_utils.h b/source/blender/python/generic/py_capi_utils.h
index 04cfc8801eb..3f89e1d82a0 100644
--- a/source/blender/python/generic/py_capi_utils.h
+++ b/source/blender/python/generic/py_capi_utils.h
@@ -75,12 +75,13 @@ typedef struct PyC_FlagSet {
} PyC_FlagSet;
char *PyC_FlagSet_AsString(PyC_FlagSet *item);
-int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value);
-int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *value, const char *error_prefix);
+int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *r_value);
+int PyC_FlagSet_ValueFromID(PyC_FlagSet *item, const char *identifier, int *r_value, const char *error_prefix);
int PyC_FlagSet_ToBitfield(PyC_FlagSet *items, PyObject *value, int *r_value, const char *error_prefix);
PyObject *PyC_FlagSet_FromBitfield(PyC_FlagSet *items, int flag);
-bool PyC_RunString_AsNumber(const char *expr, double *value, const char *filename);
+bool PyC_RunString_AsNumber(const char *expr, const char *filename, double *r_value);
+bool PyC_RunString_AsString(const char *expr, const char *filename, char **r_value);
int PyC_ParseBool(PyObject *o, void *p);
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 311f621e13b..55e477b0214 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -572,21 +572,58 @@ void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
/**
* \return success
*/
-bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value, const bool verbose)
+bool BPY_execute_string_as_number(bContext *C, const char *expr, const bool verbose, double *r_value)
{
PyGILState_STATE gilstate;
bool ok = true;
- if (!value || !expr) return -1;
+ if (!r_value || !expr) {
+ return -1;
+ }
+
+ if (expr[0] == '\0') {
+ *r_value = 0.0;
+ return ok;
+ }
+
+ bpy_context_set(C, &gilstate);
+
+ ok = PyC_RunString_AsNumber(expr, "<blender button>", r_value);
+
+ if (ok == false) {
+ if (verbose) {
+ BPy_errors_to_report_ex(CTX_wm_reports(C), false, false);
+ }
+ else {
+ PyErr_Clear();
+ }
+ }
+
+ bpy_context_clear(C, &gilstate);
+
+ return ok;
+}
+
+/**
+ * \return success
+ */
+bool BPY_execute_string_as_string(bContext *C, const char *expr, const bool verbose, char **r_value)
+{
+ PyGILState_STATE gilstate;
+ bool ok = true;
+
+ if (!r_value || !expr) {
+ return -1;
+ }
if (expr[0] == '\0') {
- *value = 0.0;
+ *r_value = NULL;
return ok;
}
bpy_context_set(C, &gilstate);
- ok = PyC_RunString_AsNumber(expr, value, "<blender button>");
+ ok = PyC_RunString_AsString(expr, "<blender button>", r_value);
if (ok == false) {
if (verbose) {
@@ -602,6 +639,7 @@ bool BPY_execute_string_as_number(bContext *C, const char *expr, double *value,
return ok;
}
+
bool BPY_execute_string_ex(bContext *C, const char *expr, bool use_eval)
{
PyGILState_STATE gilstate;
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index b8c9b3ff9e9..df1c4155a6d 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -174,7 +174,6 @@ static eSpace_Type rna_Space_refine_reverse(StructRNA *srna)
if (srna == &RNA_SpaceConsole) return SPACE_CONSOLE;
if (srna == &RNA_SpaceUserPreferences) return SPACE_USERPREF;
if (srna == &RNA_SpaceClipEditor) return SPACE_CLIP;
- if (srna == &RNA_SpaceCollectionManager) return SPACE_COLLECTIONS;
return SPACE_EMPTY;
}
diff --git a/source/blender/python/intern/bpy_utils_units.c b/source/blender/python/intern/bpy_utils_units.c
index 974d7c5549c..e0c70483e3c 100644
--- a/source/blender/python/intern/bpy_utils_units.c
+++ b/source/blender/python/intern/bpy_utils_units.c
@@ -201,7 +201,7 @@ static PyObject *bpyunits_to_value(PyObject *UNUSED(self), PyObject *args, PyObj
bUnit_ReplaceString(str, (int)str_len, uref, scale, usys, ucat);
- if (!PyC_RunString_AsNumber(str, &result, "<bpy_units_api>")) {
+ if (!PyC_RunString_AsNumber(str, "<bpy_units_api>", &result)) {
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
diff --git a/source/blender/python/intern/gpu_offscreen.c b/source/blender/python/intern/gpu_offscreen.c
index c4863b2a92f..da8e5d69f02 100644
--- a/source/blender/python/intern/gpu_offscreen.c
+++ b/source/blender/python/intern/gpu_offscreen.c
@@ -192,26 +192,28 @@ PyDoc_STRVAR(pygpu_offscreen_draw_view3d_doc,
);
static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *args, PyObject *kwds)
{
- static const char *kwlist[] = {"scene", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
+ static const char *kwlist[] = {"scene", "render_layer", "view3d", "region", "projection_matrix", "modelview_matrix", NULL};
MatrixObject *py_mat_modelview, *py_mat_projection;
- PyObject *py_scene, *py_region, *py_view3d;
+ PyObject *py_scene, *py_scene_layer, *py_region, *py_view3d;
Scene *scene;
+ SceneLayer *sl;
View3D *v3d;
ARegion *ar;
GPUFX *fx;
GPUFXSettings fx_settings;
- void *rv3d_mats;
+ struct RV3DMatrixStore *rv3d_mats;
BPY_GPU_OFFSCREEN_CHECK_OBJ(self);
if (!PyArg_ParseTupleAndKeywords(
- args, kwds, "OOOO&O&:draw_view3d", (char **)(kwlist),
- &py_scene, &py_view3d, &py_region,
+ args, kwds, "OOOOO&O&:draw_view3d", (char **)(kwlist),
+ &py_scene, &py_scene_layer, &py_view3d, &py_region,
pygpu_offscreen_check_matrix, &py_mat_projection,
pygpu_offscreen_check_matrix, &py_mat_modelview) ||
(!(scene = PyC_RNA_AsPointer(py_scene, "Scene")) ||
+ !(sl = PyC_RNA_AsPointer(py_scene_layer, "SceneLayer")) ||
!(v3d = PyC_RNA_AsPointer(py_view3d, "SpaceView3D")) ||
!(ar = PyC_RNA_AsPointer(py_region, "Region"))))
{
@@ -222,7 +224,7 @@ static PyObject *pygpu_offscreen_draw_view3d(BPy_GPUOffScreen *self, PyObject *a
fx_settings = v3d->fx_settings; /* full copy */
- ED_view3d_draw_offscreen_init(scene, v3d);
+ ED_view3d_draw_offscreen_init(scene, sl, v3d);
rv3d_mats = ED_view3d_mats_rv3d_backup(ar->regiondata);
diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c
index 4e980e4c0e6..bd44e77e7c6 100644
--- a/source/blender/python/mathutils/mathutils_Matrix.c
+++ b/source/blender/python/mathutils/mathutils_Matrix.c
@@ -1301,7 +1301,7 @@ PyDoc_STRVAR(Matrix_to_scale_doc,
" :return: Return the scale of a matrix.\n"
" :rtype: :class:`Vector`\n"
"\n"
-" .. note:: This method does not return negative a scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
+" .. note:: This method does not return a negative scale on any axis because it is not possible to obtain this data from the matrix alone.\n"
);
static PyObject *Matrix_to_scale(MatrixObject *self)
{
@@ -1390,11 +1390,11 @@ PyDoc_STRVAR(Matrix_invert_doc,
"\n"
" Set the matrix to its inverse.\n"
"\n"
-" :arg fallback: Set the matrix to this value when the inverse can't be calculated\n"
+" :arg fallback: Set the matrix to this value when the inverse cannot be calculated\n"
" (instead of raising a :exc:`ValueError` exception).\n"
" :type fallback: :class:`Matrix`\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: `Inverse matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_invert(MatrixObject *self, PyObject *args)
{
@@ -1505,7 +1505,7 @@ PyDoc_STRVAR(Matrix_invert_safe_doc,
" If degenerated (e.g. zero scale on an axis), add some epsilon to its diagonal, to get an invertible one.\n"
" If tweaked matrix is still degenerated, set to the identity matrix instead.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Inverse_matrix>\n"
+" .. seealso:: `Inverse Matrix <https://en.wikipedia.org/wiki/Inverse_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_invert_safe(MatrixObject *self)
{
@@ -1554,9 +1554,9 @@ PyDoc_STRVAR(Matrix_adjugate_doc,
"\n"
" Set the matrix to its adjugate.\n"
"\n"
-" .. note:: When the matrix cant be adjugated a :exc:`ValueError` exception is raised.\n"
+" .. note:: When the matrix cannot be adjugated a :exc:`ValueError` exception is raised.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Adjugate_matrix>\n"
+" .. seealso:: `Adjugate matrix <https://en.wikipedia.org/wiki/Adjugate_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_adjugate(MatrixObject *self)
{
@@ -1733,7 +1733,7 @@ PyDoc_STRVAR(Matrix_determinant_doc,
" :return: Return the determinant of a matrix.\n"
" :rtype: float\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Determinant>\n"
+" .. seealso:: `Determinant <https://en.wikipedia.org/wiki/Determinant>` on Wikipedia.\n"
);
static PyObject *Matrix_determinant(MatrixObject *self)
{
@@ -1755,7 +1755,7 @@ PyDoc_STRVAR(Matrix_transpose_doc,
"\n"
" Set the matrix to its transpose.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Transpose>\n"
+" .. seealso:: `Transpose <https://en.wikipedia.org/wiki/Transpose>` on Wikipedia.\n"
);
static PyObject *Matrix_transpose(MatrixObject *self)
{
@@ -1887,10 +1887,10 @@ PyDoc_STRVAR(Matrix_identity_doc,
"\n"
" Set the matrix to the identity matrix.\n"
"\n"
-" .. note:: An object with zero location and rotation, a scale of one,\n"
+" .. note:: An object with a location and rotation of zero, and a scale of one\n"
" will have an identity matrix.\n"
"\n"
-" .. seealso:: <https://en.wikipedia.org/wiki/Identity_matrix>\n"
+" .. seealso:: `Identity matrix <https://en.wikipedia.org/wiki/Identity_matrix>` on Wikipedia.\n"
);
static PyObject *Matrix_identity(MatrixObject *self)
{
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 27fa119bc88..024d8296b8f 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
../makesrna
../physics
../draw
+ ../../../intern/atomic
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index f1b3534b40a..bac3b5982c4 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -39,7 +39,7 @@
struct bNode;
struct bNodeTree;
-struct CollectionEngineSettings;
+struct IDProperty;
struct Main;
struct Object;
struct Render;
@@ -100,7 +100,9 @@ typedef struct RenderEngineType {
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
- void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
+ void (*collection_settings_create)(struct RenderEngine *engine, struct IDProperty *props);
+
+ struct DrawEngineType *draw_engine;
/* RNA integration */
ExtensionRNA ext;
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 094e62e6ceb..1ea99f406ba 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -4975,14 +4975,13 @@ static void add_group_render_dupli_obs(Render *re, Group *group, int nolamps, in
}
}
-static void database_init_objects(Render *re, unsigned int renderlay, int nolamps, int onlyselected, Object *actob, int timeoffset)
+static void database_init_objects(Render *re, unsigned int UNUSED(renderlay), int nolamps, int onlyselected, Object *actob, int timeoffset)
{
- BaseLegacy *base;
+ Base *base;
Object *ob;
Group *group;
ObjectInstanceRen *obi;
Scene *sce_iter;
- int lay, vectorlay;
/* for duplis we need the Object texture mapping to work as if
* untransformed, set_dupli_tex_mat sets the matrix to allow that
@@ -5010,14 +5009,18 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
for (SETLOOPER(re->scene, sce_iter, base)) {
ob= base->object;
+#if 0
+ TODO_LAYER; /* investigate if this is an issue*/
/* in the prev/next pass for making speed vectors, avoid creating
* objects that are not on a renderlayer with a vector pass, can
* save a lot of time in complex scenes */
vectorlay= get_vector_renderlayers(re->scene);
- lay= (timeoffset)? renderlay & vectorlay: renderlay;
+#endif
- /* if the object has been restricted from rendering in the outliner, ignore it */
- if (is_object_restricted(re, ob)) continue;
+ /* if the object is not visible, ignore it */
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ continue;
+ }
/* OB_DONE means the object itself got duplicated, so was already converted */
if (ob->flag & OB_DONE) {
@@ -5030,7 +5033,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
}
}
}
- else if ((base->lay & lay) || (ob->type==OB_LAMP && (base->lay & re->lay)) ) {
+ else if (((base->flag & BASE_VISIBLED) != 0) || (ob->type==OB_LAMP)) {
if ((ob->transflag & OB_DUPLI) && (ob->type!=OB_MBALL)) {
DupliObject *dob;
ListBase *duplilist;
diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c
index 7de20ab2056..33258d04673 100644
--- a/source/blender/render/intern/source/envmap.c
+++ b/source/blender/render/intern/source/envmap.c
@@ -51,6 +51,7 @@
#include "BKE_main.h"
#include "BKE_image.h" /* BKE_imbuf_write */
+#include "BKE_layer.h"
#include "BKE_texture.h"
#include "BKE_scene.h"
@@ -247,17 +248,14 @@ static void envmap_transmatrix(float mat[4][4], int part)
static void env_set_imats(Render *re)
{
- BaseLegacy *base;
float mat[4][4];
-
- base = re->scene->base.first;
- while (base) {
- mul_m4_m4m4(mat, re->viewmat, base->object->obmat);
- invert_m4_m4(base->object->imat, mat);
-
- base = base->next;
+
+ FOREACH_SCENE_OBJECT(re->scene, ob)
+ {
+ mul_m4_m4m4(mat, re->viewmat, ob->obmat);
+ invert_m4_m4(ob->imat, mat);
}
-
+ FOREACH_SCENE_OBJECT_END
}
/* ------------------------------------------------------------------------- */
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index 1744d88a14f..8c1cdb3dc8a 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -71,7 +71,7 @@
static RenderEngineType internal_render_type = {
NULL, NULL,
"BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -80,7 +80,7 @@ static RenderEngineType internal_render_type = {
static RenderEngineType internal_game_type = {
NULL, NULL,
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -94,7 +94,7 @@ void RE_engines_init(void)
#ifdef WITH_GAMEENGINE
RE_engines_register(NULL, &internal_game_type);
#endif
- DRW_engines_init();
+ DRW_engines_register();
}
void RE_engines_exit(void)
@@ -121,6 +121,9 @@ void RE_engines_exit(void)
void RE_engines_register(Main *bmain, RenderEngineType *render_type)
{
+ if (render_type->draw_engine) {
+ DRW_engine_register(render_type->draw_engine);
+ }
if (render_type->collection_settings_create) {
BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create);
}
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 34966e1b111..7598cb3ff6b 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -2012,14 +2012,14 @@ bool RE_allow_render_generic_object(Object *ob)
#define DEPSGRAPH_WORKAROUND_HACK
#ifdef DEPSGRAPH_WORKAROUND_HACK
-static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
+static void tag_dependend_objects_for_render(Scene *scene, int UNUSED(renderlay))
{
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
for (SETLOOPER(scene, sce_iter, base)) {
Object *object = base->object;
- if ((base->lay & renderlay) == 0) {
+ if ((base->flag & BASE_VISIBLED) == 0) {
continue;
}
diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c
index a03ea9cb896..fb047aad897 100644
--- a/source/blender/render/intern/source/pointdensity.c
+++ b/source/blender/render/intern/source/pointdensity.c
@@ -983,11 +983,12 @@ void RE_point_density_minmax(
}
else {
float radius[3] = {pd->radius, pd->radius, pd->radius};
- float *loc, *size;
+ BoundBox *bb = BKE_object_boundbox_get(object);
- if (BKE_object_obdata_texspace_get(pd->object, NULL, &loc, &size, NULL)) {
- sub_v3_v3v3(r_min, loc, size);
- add_v3_v3v3(r_max, loc, size);
+ if (bb != NULL) {
+ BLI_assert((bb->flag & BOUNDBOX_DIRTY) == 0);
+ copy_v3_v3(r_min, bb->vec[0]);
+ copy_v3_v3(r_max, bb->vec[6]);
/* Adjust texture space to include density points on the boundaries. */
sub_v3_v3(r_min, radius);
add_v3_v3(r_max, radius);
diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c
index b4a14f5337d..42e4d4f27f6 100644
--- a/source/blender/render/intern/source/render_texture.c
+++ b/source/blender/render/intern/source/render_texture.c
@@ -1112,14 +1112,15 @@ static int multitex(Tex *tex,
const short which_output,
struct ImagePool *pool,
const bool skip_load_image,
- const bool texnode_preview)
+ const bool texnode_preview,
+ const bool use_nodes)
{
float tmpvec[3];
int retval = 0; /* return value, int:0, col:1, nor:2, everything:3 */
texres->talpha = false; /* is set when image texture returns alpha (considered premul) */
- if (tex->use_nodes && tex->nodetree) {
+ if (use_nodes && tex->use_nodes && tex->nodetree) {
retval = ntreeTexExecTree(tex->nodetree, texres, texvec, dxt, dyt, osatex, thread,
tex, which_output, R.r.cfra, texnode_preview, NULL, NULL);
}
@@ -1239,7 +1240,8 @@ static int multitex_nodes_intern(Tex *tex,
ImagePool *pool,
const bool scene_color_manage,
const bool skip_load_image,
- const bool texnode_preview)
+ const bool texnode_preview,
+ const bool use_nodes)
{
if (tex==NULL) {
memset(texres, 0, sizeof(TexResult));
@@ -1264,7 +1266,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
if (mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) {
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1311,7 +1314,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
{
ImBuf *ibuf = BKE_image_pool_acquire_ibuf(tex->ima, &tex->iuser, pool);
@@ -1341,7 +1345,8 @@ static int multitex_nodes_intern(Tex *tex,
which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ use_nodes);
}
}
@@ -1354,7 +1359,8 @@ int multitex_nodes(Tex *tex, float texvec[3], float dxt[3], float dyt[3], int os
return multitex_nodes_intern(tex, texvec, dxt, dyt, osatex, texres,
thread, which_output, shi, mtex, pool, R.scene_color_manage,
(R.r.scemode & R_NO_IMAGE_LOAD) != 0,
- (R.r.scemode & R_TEXNODE_PREVIEW) != 0);
+ (R.r.scemode & R_TEXNODE_PREVIEW) != 0,
+ true);
}
/* this is called for surface shading */
@@ -1378,7 +1384,8 @@ static int multitex_mtex(ShadeInput *shi, MTex *mtex, float texvec[3], float dxt
mtex->which_output,
pool,
skip_load_image,
- (R.r.scemode & R_TEXNODE_PREVIEW) != 0);
+ (R.r.scemode & R_TEXNODE_PREVIEW) != 0,
+ true);
}
}
@@ -1408,7 +1415,8 @@ int multitex_ext(Tex *tex,
pool,
scene_color_manage,
skip_load_image,
- false);
+ false,
+ true);
}
/* extern-tex doesn't support nodes (ntreeBeginExec() can't be called when rendering is going on)\
@@ -1417,13 +1425,19 @@ int multitex_ext(Tex *tex,
*/
int multitex_ext_safe(Tex *tex, float texvec[3], TexResult *texres, struct ImagePool *pool, bool scene_color_manage, const bool skip_load_image)
{
- int use_nodes= tex->use_nodes, retval;
-
- tex->use_nodes = false;
- retval= multitex_nodes_intern(tex, texvec, NULL, NULL, 0, texres, 0, 0, NULL, NULL, pool, scene_color_manage, skip_load_image, false);
- tex->use_nodes= use_nodes;
-
- return retval;
+ return multitex_nodes_intern(tex,
+ texvec,
+ NULL, NULL,
+ 0,
+ texres,
+ 0,
+ 0,
+ NULL, NULL,
+ pool,
+ scene_color_manage,
+ skip_load_image,
+ false,
+ false);
}
@@ -2873,7 +2887,8 @@ void do_volume_tex(ShadeInput *shi, const float *xyz, int mapto_flag, float col_
mtex->which_output,
re->pool,
skip_load_image,
- texnode_preview); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
+ texnode_preview,
+ true); /* NULL = dxt/dyt, 0 = shi->osatex - not supported */
/* texture output */
@@ -3051,7 +3066,8 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float col_r[4])
mtex->which_output,
har->pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3274,7 +3290,8 @@ void do_sky_tex(
mtex->which_output,
R.pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3500,7 +3517,8 @@ void do_lamp_tex(LampRen *la, const float lavec[3], ShadeInput *shi, float col_r
mtex->which_output,
R.pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
/* texture output */
if (rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -3614,7 +3632,8 @@ int externtex(MTex *mtex,
mtex->which_output,
pool,
skip_load_image,
- texnode_preview);
+ texnode_preview,
+ true);
if (rgb) {
texr.tin = IMB_colormanagement_get_luminance(&texr.tr);
diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c
index c4de95e863e..a8fb72fb7f8 100644
--- a/source/blender/render/intern/source/shadeoutput.c
+++ b/source/blender/render/intern/source/shadeoutput.c
@@ -2143,7 +2143,7 @@ const float (*RE_object_instance_get_matrix(struct ObjectInstanceRen *obi, int m
const float (*RE_render_current_get_matrix(int matrix_id))[4]
{
- switch(matrix_id) {
+ switch (matrix_id) {
case RE_VIEW_MATRIX:
return (const float(*)[4])R.viewmat;
case RE_VIEWINV_MATRIX:
@@ -2171,4 +2171,4 @@ float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta)
}
return result;
-} \ No newline at end of file
+}
diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c
index 5377d0eba00..752a9df0b79 100644
--- a/source/blender/render/intern/source/volume_precache.c
+++ b/source/blender/render/intern/source/volume_precache.c
@@ -60,6 +60,8 @@
#include "volumetric.h"
#include "volume_precache.h"
+#include "atomic_ops.h"
+
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
@@ -509,7 +511,8 @@ static void *vol_precache_part_test(void *data)
*/
typedef struct VolPrecacheState {
double lasttime;
- int totparts;
+ unsigned int doneparts;
+ unsigned int totparts;
} VolPrecacheState;
static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UNUSED(threadid))
@@ -574,13 +577,15 @@ static void vol_precache_part(TaskPool * __restrict pool, void *taskdata, int UN
}
}
+ unsigned int doneparts = atomic_add_and_fetch_u(&state->doneparts, 1);
+
time = PIL_check_seconds_timer();
if (time - state->lasttime > 1.0) {
ThreadMutex *mutex = BLI_task_pool_user_mutex(pool);
if (BLI_mutex_trylock(mutex)) {
char str[64];
- float ratio = (float)BLI_task_pool_tasks_done(pool)/(float)state->totparts;
+ float ratio = (float)doneparts/(float)state->totparts;
BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), (int)(100.0f * ratio));
re->i.infostr = str;
re->stats_draw(re->sdh, &re->i);
@@ -631,6 +636,7 @@ static void precache_launch_parts(Render *re, RayObject *tree, ShadeInput *shi,
/* setup task scheduler */
memset(&state, 0, sizeof(state));
+ state.doneparts = 0;
state.totparts = parts[0]*parts[1]*parts[2];
state.lasttime = PIL_check_seconds_timer();
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index fba559984cd..f510fd967c5 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -145,10 +145,6 @@ if(WITH_PYTHON)
../python
)
add_definitions(-DWITH_PYTHON)
-
- if(WITH_PYTHON_SECURITY)
- add_definitions(-DWITH_PYTHON_SECURITY)
- endif()
endif()
if(WITH_GAMEENGINE)
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 238bfa6dee8..1cabb07d556 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -239,6 +239,7 @@ void WM_operator_view3d_unit_defaults(struct bContext *C, struct wmOperator *op
int WM_operator_smooth_viewtx_get(const struct wmOperator *op);
int WM_menu_invoke_ex(struct bContext *C, struct wmOperator *op, int opcontext);
int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
+int WM_enum_search_invoke_previews(struct bContext *C, struct wmOperator *op, short prv_cols, short prv_rows);
int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
/* invoke callback, confirm menu + exec */
int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event);
@@ -263,6 +264,7 @@ int WM_operator_confirm_message(struct bContext *C, struct wmOperator *o
/* operator api */
void WM_operator_free (struct wmOperator *op);
+void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op);
void WM_operator_type_set(struct wmOperator *op, struct wmOperatorType *ot);
void WM_operator_stack_clear(struct wmWindowManager *wm);
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot);
@@ -287,6 +289,7 @@ int WM_operator_call (struct bContext *C, struct wmOperator *op);
int WM_operator_call_notest(struct bContext *C, struct wmOperator *op);
int WM_operator_repeat (struct bContext *C, struct wmOperator *op);
bool WM_operator_repeat_check(const struct bContext *C, struct wmOperator *op);
+bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op);
int WM_operator_name_call_ptr(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties);
int WM_operator_name_call(struct bContext *C, const char *opstring, short context, struct PointerRNA *properties);
int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, const bool is_undo);
@@ -420,9 +423,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid);
void wmSubWindowSet (struct wmWindow *win, int swinid);
void wmSubWindowScissorSet (struct wmWindow *win, int swinid, const struct rcti *srct, bool srct_pad);
- /* OpenGL utilities with safety check + working in modelview matrix mode */
-void wmFrustum (float x1, float x2, float y1, float y2, float n, float f);
-void wmOrtho (float x1, float x2, float y1, float y2, float n, float f);
+ /* OpenGL utilities with safety check */
void wmOrtho2 (float x1, float x2, float y1, float y2);
/* use for conventions (avoid hard-coded offsets all over) */
void wmOrtho2_region_pixelspace(const struct ARegion *ar);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 49e70b4f200..84209a0e3c8 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -364,7 +364,6 @@ typedef struct wmNotifier {
#define ND_SPACE_CHANGED (18<<16) /*sent to a new editor type after it's replaced an old one*/
#define ND_SPACE_CLIP (19<<16)
#define ND_SPACE_FILE_PREVIEW (20<<16)
-#define ND_SPACE_COLLECTIONS (21<<16)
/* subtype, 256 entries too */
#define NOTE_SUBTYPE 0x0000FF00
@@ -544,7 +543,15 @@ typedef struct wmOperatorType {
* canceled due to some external reason, cancel is called
* - see defines below for return values */
int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
+
+ /* Called when a modal operator is canceled (not used often).
+ * Internal cleanup can be done here if needed. */
void (*cancel)(struct bContext *, struct wmOperator *);
+
+ /* Modal is used for operators which continuously run, eg:
+ * fly mode, knife tool, circle select are all examples of modal operators.
+ * Modal operators can handle events which would normally access other operators,
+ * they keep running until they don't return `OPERATOR_RUNNING_MODAL`. */
int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT;
/* verify if the operator can be executed in the current context, note
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index b76a1f1d422..4351cd22b18 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -107,6 +107,17 @@ void WM_operator_free(wmOperator *op)
MEM_freeN(op);
}
+void WM_operator_free_all_after(wmWindowManager *wm, struct wmOperator *op)
+{
+ op = op->next;
+ while (op != NULL) {
+ wmOperator *op_next = op->next;
+ BLI_remlink(&wm->operators, op);
+ WM_operator_free(op);
+ op = op_next;
+ }
+}
+
/**
* Use with extreme care!,
* properties, customdata etc - must be compatible.
@@ -149,18 +160,23 @@ static void wm_reports_free(wmWindowManager *wm)
void wm_operator_register(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
- int tot;
+ int tot = 0;
BLI_addtail(&wm->operators, op);
- tot = BLI_listbase_count(&wm->operators);
-
- while (tot > MAX_OP_REGISTERED) {
- wmOperator *opt = wm->operators.first;
- BLI_remlink(&wm->operators, opt);
- WM_operator_free(opt);
- tot--;
+
+ /* only count registered operators */
+ while (op) {
+ wmOperator *op_prev = op->prev;
+ if (op->type->flag & OPTYPE_REGISTER) {
+ tot += 1;
+ }
+ if (tot > MAX_OP_REGISTERED) {
+ BLI_remlink(&wm->operators, op);
+ WM_operator_free(op);
+ }
+ op = op_prev;
}
-
+
/* so the console is redrawn */
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_INFO_REPORT, NULL);
WM_event_add_notifier(C, NC_WM | ND_HISTORY, NULL);
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
index 2d1dcd7f3c9..0402a528e8d 100644
--- a/source/blender/windowmanager/intern/wm_dragdrop.c
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -46,6 +46,8 @@
#include "BKE_context.h"
+#include "GPU_shader.h"
+
#include "IMB_imbuf_types.h"
#include "UI_interface.h"
@@ -332,8 +334,10 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
if (rect)
drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy);
else {
- glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
- glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale);
+ float col[4] = {1.0f, 1.0f, 1.0f, 0.65f}; /* this blends texture */
+ immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR);
+ immDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST,
+ drag->imb->rect, drag->scale, drag->scale, 1.0f, 1.0f, col);
}
}
else {
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 809a5cac6e8..daba01cb3a6 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -57,8 +57,6 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
-#include "GPU_glew.h"
-#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
#include "RE_engine.h"
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index d9d8fbc6cfa..2e04f4ea929 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -713,7 +713,9 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, bool ca
*/
static bool wm_operator_register_check(wmWindowManager *wm, wmOperatorType *ot)
{
- return wm && (wm->op_undo_depth == 0) && (ot->flag & OPTYPE_REGISTER);
+ /* Check undo flag here since undo operators are also added to the list,
+ * to support checking if the same operator is run twice. */
+ return wm && (wm->op_undo_depth == 0) && (ot->flag & (OPTYPE_REGISTER | OPTYPE_UNDO));
}
static void wm_operator_finished(bContext *C, wmOperator *op, const bool repeat)
@@ -876,6 +878,20 @@ bool WM_operator_repeat_check(const bContext *UNUSED(C), wmOperator *op)
return false;
}
+bool WM_operator_is_repeat(const bContext *C, const wmOperator *op)
+{
+ /* may be in the operators list or not */
+ wmOperator *op_prev;
+ if (op->prev == NULL && op->next == NULL) {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ op_prev = wm->operators.last;
+ }
+ else {
+ op_prev = op->prev;
+ }
+ return (op_prev && (op->type == op_prev->type));
+}
+
static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot,
PointerRNA *properties, ReportList *reports)
{
@@ -3275,6 +3291,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U
GHOST_TEventCursorData *cd = customdata;
copy_v2_v2_int(&event.x, &cd->x);
+ wm_stereo3d_mouse_offset_apply(win, &event.x);
+
event.type = MOUSEMOVE;
wm_event_add_mousemove(win, &event);
copy_v2_v2_int(&evt->x, &event.x);
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 05d63869074..1095195acd5 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -316,7 +316,7 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist)
}
/* in case UserDef was read, we re-initialize all, and do versioning */
-static void wm_init_userdef(bContext *C, const bool from_memory)
+static void wm_init_userdef(bContext *C, const bool use_factory_settings)
{
Main *bmain = CTX_data_main(C);
@@ -336,7 +336,7 @@ static void wm_init_userdef(bContext *C, const bool from_memory)
}
/* avoid re-saving for every small change to our prefs, allow overrides */
- if (from_memory) {
+ if (use_factory_settings) {
BLO_update_defaults_userpref_blend();
}
@@ -470,6 +470,10 @@ static void wm_file_read_post(bContext *C, bool is_startup_file)
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
+ /* Only run when we have a template path found. */
+ if (BKE_appdir_app_template_any()) {
+ BPY_execute_string(C, "__import__('bl_app_template_utils').reset()");
+ }
/* sync addons, these may have changed from the defaults */
BPY_execute_string(C, "__import__('addon_utils').reset_all()");
@@ -554,7 +558,7 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/* confusing this global... */
G.relbase_valid = 1;
- retval = BKE_blendfile_read(C, filepath, reports);
+ retval = BKE_blendfile_read(C, filepath, reports, 0);
/* when loading startup.blend's, we can be left with a blank path */
if (G.main->name[0]) {
G.save_over = 1;
@@ -629,22 +633,34 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
/**
- * called on startup, (context entirely filled with NULLs)
- * or called for 'New File'
- * both startup.blend and userpref.blend are checked
- * the optional parameter custom_file points to an alternative startup page
- * custom_file can be NULL
+ * Called on startup, (context entirely filled with NULLs)
+ * or called for 'New File' both startup.blend and userpref.blend are checked.
+ *
+ * \param use_factory_settings: Ignore on-disk startup file, use bundled ``datatoc_startup_blend`` instead.
+ * Used for "Restore Factory Settings".
+ * \param filepath_startup_override: Optional path pointing to an alternative blend file (may be NULL).
+ * \param app_template_override: Template to use instead of the template defined in user-preferences.
+ * When not-null, this is written into the user preferences.
*/
-int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const char *custom_file)
+int wm_homefile_read(
+ bContext *C, ReportList *reports,
+ bool use_factory_settings, bool use_empty_data,
+ const char *filepath_startup_override, const char *app_template_override)
{
ListBase wmbase;
- char startstr[FILE_MAX];
- char prefstr[FILE_MAX];
- int success = 0;
+ bool success = false;
+
+ char filepath_startup[FILE_MAX];
+ char filepath_userdef[FILE_MAX];
+
+ /* When 'app_template' is set: '{BLENDER_USER_CONFIG}/{app_template}' */
+ char app_template_system[FILE_MAX];
+ /* When 'app_template' is set: '{BLENDER_SYSTEM_SCRIPTS}/startup/bl_app_templates_system/{app_template}' */
+ char app_template_config[FILE_MAX];
/* Indicates whether user preferences were really load from memory.
*
- * This is used for versioning code, and for this we can not rely on from_memory
+ * This is used for versioning code, and for this we can not rely on use_factory_settings
* passed via argument. This is because there might be configuration folder
* exists but it might not have userpref.blend and in this case we fallback to
* reading home file from memory.
@@ -652,9 +668,10 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
* And in this case versioning code is to be run.
*/
bool read_userdef_from_memory = true;
+ eBLOReadSkip skip_flags = 0;
/* options exclude eachother */
- BLI_assert((from_memory && custom_file) == 0);
+ BLI_assert((use_factory_settings && filepath_startup_override) == 0);
if ((G.f & G_SCRIPT_OVERRIDE_PREF) == 0) {
BKE_BIT_TEST_SET(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_SCRIPT_AUTOEXEC);
@@ -665,71 +682,146 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
UI_view2d_zoom_cache_reset();
G.relbase_valid = 0;
- if (!from_memory) {
- const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
- if (custom_file) {
- BLI_strncpy(startstr, custom_file, FILE_MAX);
- if (cfgdir) {
- BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
- }
- else {
- prefstr[0] = '\0';
- }
+ /* put aside screens to match with persistent windows later */
+ wm_window_match_init(C, &wmbase);
+
+ filepath_startup[0] = '\0';
+ filepath_userdef[0] = '\0';
+ app_template_system[0] = '\0';
+ app_template_config[0] = '\0';
+
+ const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
+ if (!use_factory_settings) {
+ if (cfgdir) {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), cfgdir, BLENDER_STARTUP_FILE, NULL);
+ BLI_path_join(filepath_userdef, sizeof(filepath_startup), cfgdir, BLENDER_USERPREF_FILE, NULL);
}
- else if (cfgdir) {
- BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE);
- BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE);
+ else {
+ use_factory_settings = true;
+ }
+
+ if (filepath_startup_override) {
+ BLI_strncpy(filepath_startup, filepath_startup_override, FILE_MAX);
+ }
+ }
+
+ /* load preferences before startup.blend */
+ if (!use_factory_settings && BLI_exists(filepath_userdef)) {
+ UserDef *userdef = BKE_blendfile_userdef_read(filepath_userdef, NULL);
+ if (userdef != NULL) {
+ BKE_blender_userdef_set_data(userdef);
+ MEM_freeN(userdef);
+
+ read_userdef_from_memory = false;
+ skip_flags |= BLO_READ_SKIP_USERDEF;
+ printf("Read prefs: %s\n", filepath_userdef);
+ }
+ }
+
+ const char *app_template = NULL;
+
+ if (filepath_startup_override != NULL) {
+ /* pass */
+ }
+ else if (app_template_override) {
+ app_template = app_template_override;
+ }
+ else if (!use_factory_settings && U.app_template[0]) {
+ app_template = U.app_template;
+ }
+
+ if (app_template != NULL) {
+ BKE_appdir_app_template_id_search(app_template, app_template_system, sizeof(app_template_system));
+ BLI_path_join(app_template_config, sizeof(app_template_config), cfgdir, app_template, NULL);
+ }
+
+ /* insert template name into startup file */
+ if (app_template != NULL) {
+ /* note that the path is being set even when 'use_factory_settings == true'
+ * this is done so we can load a templates factory-settings */
+ if (!use_factory_settings) {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_config, BLENDER_STARTUP_FILE, NULL);
+ if (BLI_access(filepath_startup, R_OK) != 0) {
+ filepath_startup[0] = '\0';
+ }
}
else {
- startstr[0] = '\0';
- prefstr[0] = '\0';
- from_memory = 1;
+ filepath_startup[0] = '\0';
+ }
+
+ if (filepath_startup[0] == '\0') {
+ BLI_path_join(filepath_startup, sizeof(filepath_startup), app_template_system, BLENDER_STARTUP_FILE, NULL);
}
}
-
- /* put aside screens to match with persistent windows later */
- wm_window_match_init(C, &wmbase);
-
- if (!from_memory) {
- if (BLI_access(startstr, R_OK) == 0) {
- success = (BKE_blendfile_read(C, startstr, NULL) != BKE_BLENDFILE_READ_FAIL);
+
+ if (!use_factory_settings || (filepath_startup[0] != '\0')) {
+ if (BLI_access(filepath_startup, R_OK) == 0) {
+ success = (BKE_blendfile_read(C, filepath_startup, NULL, skip_flags) != BKE_BLENDFILE_READ_FAIL);
}
if (BLI_listbase_is_empty(&U.themes)) {
if (G.debug & G_DEBUG)
- printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr);
- success = 0;
+ printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", filepath_startup);
+ success = false;
}
}
- if (success == 0 && custom_file && reports) {
- BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", custom_file);
- /*We can not return from here because wm is already reset*/
+ if (success == false && filepath_startup_override && reports) {
+ /* We can not return from here because wm is already reset */
+ BKE_reportf(reports, RPT_ERROR, "Could not read '%s'", filepath_startup_override);
}
- if (success == 0) {
- success = BKE_blendfile_read_from_memory(C, datatoc_startup_blend, datatoc_startup_blend_size, NULL, true);
+ if (success == false) {
+ success = BKE_blendfile_read_from_memory(
+ C, datatoc_startup_blend, datatoc_startup_blend_size,
+ NULL, skip_flags, true);
if (BLI_listbase_is_empty(&wmbase)) {
wm_clear_default_size(C);
}
- BKE_tempdir_init(U.tempdir);
+ }
-#ifdef WITH_PYTHON_SECURITY
- /* use alternative setting for security nuts
- * otherwise we'd need to patch the binary blob - startup.blend.c */
- U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
-#endif
+ if (use_empty_data) {
+ BKE_blendfile_read_make_empty(C);
}
-
- /* check new prefs only after startup.blend was finished */
- if (!from_memory && BLI_exists(prefstr)) {
- int done = BKE_blendfile_read_userdef(prefstr, NULL);
- if (done != BKE_BLENDFILE_READ_FAIL) {
- read_userdef_from_memory = false;
- printf("Read new prefs: %s\n", prefstr);
+
+ /* Load template preferences,
+ * unlike regular preferences we only use some of the settings,
+ * see: BKE_blender_userdef_set_app_template */
+ if (app_template_system[0] != '\0') {
+ char temp_path[FILE_MAX];
+ temp_path[0] = '\0';
+ if (!use_factory_settings) {
+ BLI_path_join(temp_path, sizeof(temp_path), app_template_config, BLENDER_USERPREF_FILE, NULL);
+ if (BLI_access(temp_path, R_OK) != 0) {
+ temp_path[0] = '\0';
+ }
+ }
+
+ if (temp_path[0] == '\0') {
+ BLI_path_join(temp_path, sizeof(temp_path), app_template_system, BLENDER_USERPREF_FILE, NULL);
+ }
+
+ UserDef *userdef_template = NULL;
+ /* just avoids missing file warning */
+ if (BLI_exists(temp_path)) {
+ userdef_template = BKE_blendfile_userdef_read(temp_path, NULL);
+ }
+ if (userdef_template == NULL) {
+ /* we need to have preferences load to overwrite preferences from previous template */
+ userdef_template = BKE_blendfile_userdef_read_from_memory(
+ datatoc_startup_blend, datatoc_startup_blend_size, NULL);
+ }
+ if (userdef_template) {
+ BKE_blender_userdef_set_app_template(userdef_template);
+ BKE_blender_userdef_free_data(userdef_template);
+ MEM_freeN(userdef_template);
}
}
-
+
+ if (app_template_override) {
+ BLI_strncpy(U.app_template, app_template_override, sizeof(U.app_template));
+ }
+
/* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise
* can remove this eventually, only in a 2.53 and older, now its not written */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
@@ -744,11 +836,14 @@ int wm_homefile_read(bContext *C, ReportList *reports, bool from_memory, const c
G.main->name[0] = '\0';
/* When loading factory settings, the reset solid OpenGL lights need to be applied. */
- if (!G.background) GPU_default_lights();
-
- /* XXX */
- G.save_over = 0; // start with save preference untitled.blend
- G.fileflags &= ~G_FILE_AUTOPLAY; /* disable autoplay in startup.blend... */
+ if (!G.background) {
+ GPU_default_lights();
+ }
+
+ /* start with save preference untitled.blend */
+ G.save_over = 0;
+ /* disable auto-play in startup.blend... */
+ G.fileflags &= ~G_FILE_AUTOPLAY;
wm_file_read_post(C, true);
@@ -879,7 +974,7 @@ static void wm_history_file_update(void)
/* screen can be NULL */
-static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **thumb_pt)
+static ImBuf *blend_file_thumb(Scene *scene, SceneLayer *sl, bScreen *screen, BlendThumbnail **thumb_pt)
{
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
@@ -916,14 +1011,14 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, BlendThumbnail **t
/* gets scaled to BLEN_THUMB_SIZE */
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(
- scene, scene->camera,
+ scene, sl, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, 0, false, NULL,
NULL, NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(
- scene, v3d, ar,
+ scene, sl, v3d, ar,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
IB_rect, false, R_ALPHAPREMUL, 0, false, NULL,
NULL, NULL, err_out);
@@ -1019,7 +1114,7 @@ static int wm_file_write(bContext *C, const char *filepath, int fileflags, Repor
/* Main now can store a .blend thumbnail, usefull for background mode or thumbnail customization. */
main_thumb = thumb = CTX_data_main(C)->blen_thumb;
if ((U.flag & USER_SAVE_PREVIEWS) && BLI_thread_is_main()) {
- ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_wm_screen(C), &thumb);
+ ibuf_thumb = blend_file_thumb(CTX_data_scene(C), CTX_data_scene_layer(C), CTX_wm_screen(C), &thumb);
}
/* operator now handles overwrite checks */
@@ -1264,6 +1359,13 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
char filepath[FILE_MAX];
int fileflags;
+ const char *app_template = U.app_template[0] ? U.app_template : NULL;
+ const char * const cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, app_template);
+ if (cfgdir == NULL) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create user config path");
+ return OPERATOR_CANCELLED;
+ }
+
BLI_callback_exec(G.main, NULL, BLI_CB_EVT_SAVE_PRE);
/* check current window and close it if temp */
@@ -1273,7 +1375,8 @@ static int wm_homefile_write_exec(bContext *C, wmOperator *op)
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE);
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_STARTUP_FILE, NULL);
+
printf("trying to save homefile at %s ", filepath);
ED_editors_flush_edits(C, false);
@@ -1351,21 +1454,44 @@ static int wm_userpref_write_exec(bContext *C, wmOperator *op)
{
wmWindowManager *wm = CTX_wm_manager(C);
char filepath[FILE_MAX];
+ const char *cfgdir;
+ bool ok = false;
/* update keymaps in user preferences */
WM_keyconfig_update(wm);
- BLI_make_file_string("/", filepath, BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL), BLENDER_USERPREF_FILE);
- printf("trying to save userpref at %s ", filepath);
-
- if (BKE_blendfile_write_userdef(filepath, op->reports) == 0) {
- printf("fail\n");
- return OPERATOR_CANCELLED;
+ if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, NULL))) {
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ printf("trying to save userpref at %s ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, op->reports) != 0) {
+ printf("ok\n");
+ ok = true;
+ }
+ else {
+ printf("fail\n");
+ }
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create userpref path");
}
- printf("ok\n");
+ if (U.app_template[0] && (cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
+ /* Also save app-template prefs */
+ BLI_path_join(filepath, sizeof(filepath), cfgdir, BLENDER_USERPREF_FILE, NULL);
+ printf("trying to save app-template userpref at %s ", filepath);
+ if (BKE_blendfile_userdef_write(filepath, op->reports) == 0) {
+ printf("fail\n");
+ ok = true;
+ }
+ else {
+ printf("ok\n");
+ }
+ }
+ else if (U.app_template[0]) {
+ BKE_report(op->reports, RPT_ERROR, "Unable to create app-template userpref path");
+ }
- return OPERATOR_FINISHED;
+ return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
void WM_OT_save_userpref(wmOperatorType *ot)
@@ -1400,11 +1526,11 @@ void WM_OT_read_history(wmOperatorType *ot)
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
- const bool from_memory = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
+ const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
char filepath_buf[FILE_MAX];
const char *filepath = NULL;
- if (!from_memory) {
+ if (!use_factory_settings) {
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "filepath");
/* This can be used when loading of a start-up file should only change
@@ -1426,7 +1552,34 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
G.fileflags &= ~G_FILE_NO_UI;
}
- return wm_homefile_read(C, op->reports, from_memory, filepath) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ char app_template_buf[sizeof(U.app_template)];
+ const char *app_template;
+ PropertyRNA *prop_app_template = RNA_struct_find_property(op->ptr, "app_template");
+ const bool use_splash = !use_factory_settings && RNA_boolean_get(op->ptr, "use_splash");
+ const bool use_empty_data = RNA_boolean_get(op->ptr, "use_empty");
+
+ if (prop_app_template && RNA_property_is_set(op->ptr, prop_app_template)) {
+ RNA_property_string_get(op->ptr, prop_app_template, app_template_buf);
+ app_template = app_template_buf;
+ }
+ else if (!use_factory_settings) {
+ /* TODO: dont reset prefs on 'New File' */
+ BLI_strncpy(app_template_buf, U.app_template, sizeof(app_template_buf));
+ app_template = app_template_buf;
+ }
+ else {
+ app_template = NULL;
+ }
+
+ if (wm_homefile_read(C, op->reports, use_factory_settings, use_empty_data, filepath, app_template)) {
+ if (use_splash) {
+ WM_init_splash(C);
+ }
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
}
void WM_OT_read_homefile(wmOperatorType *ot)
@@ -1449,17 +1602,36 @@ void WM_OT_read_homefile(wmOperatorType *ot)
"Load user interface setup from the .blend file");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ /* So the splash can be kept open after loading a file (for templates). */
+ prop = RNA_def_boolean(ot->srna, "use_splash", false, "Splash", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
/* omit poll to run in background mode */
}
void WM_OT_read_factory_settings(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
ot->name = "Load Factory Settings";
ot->idname = "WM_OT_read_factory_settings";
ot->description = "Load default file and user preferences";
ot->invoke = WM_operator_confirm;
ot->exec = wm_homefile_read_exec;
+
+ prop = RNA_def_string(ot->srna, "app_template", "Template", sizeof(U.app_template), "", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_boolean(ot->srna, "use_empty", false, "Empty", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
/* omit poll to run in background mode */
}
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 46203333eb5..d49c83fa729 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -45,15 +45,14 @@
#include "BKE_context.h"
-
#include "WM_api.h"
#include "WM_types.h"
#include "wm.h"
#include "wm_subwindow.h"
#include "wm_draw.h"
-#include "GPU_basic_shader.h"
+#include "GPU_immediate.h"
#include "BIF_glutil.h"
@@ -168,69 +167,156 @@ int wm_gesture_evaluate(wmGesture *gesture)
/* ******************* gesture draw ******************* */
+static void wm_gesture_draw_line(wmGesture *gt)
+{
+ rcti *rect = (rcti *)gt->customdata;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned line_origin = add_attrib(format, "line_origin", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
+
+ immUniform4f("color1", 0.4f, 0.4f, 0.4f, 1.0f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 8.0f);
+ immUniform1f("dash_width_on", 4.0f);
+
+ float xmin = (float)rect->xmin;
+ float ymin = (float)rect->ymin;
+
+ immBegin(PRIM_LINES, 2);
+
+ immAttrib2f(line_origin, xmin, ymin);
+ immVertex2f(pos, xmin, ymin);
+ immAttrib2f(line_origin, xmin, ymin);
+ immVertex2f(pos, (float)rect->xmax, (float)rect->ymax);
+
+ immEnd();
+
+ immUnbindProgram();
+}
+
+static void imm_draw_line_box_dashed(unsigned pos, unsigned line_origin, float x1, float y1, float x2, float y2)
+{
+ immBegin(PRIM_LINES, 8);
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x1, y1);
+ immVertex2f(pos, x1, y2);
+ immAttrib2f(line_origin, x1, y2);
+ immVertex2f(pos, x1, y2);
+ immVertex2f(pos, x2, y2);
+ immAttrib2f(line_origin, x2, y1);
+ immVertex2f(pos, x2, y2);
+ immVertex2f(pos, x2, y1);
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x2, y1);
+ immVertex2f(pos, x1, y1);
+ immEnd();
+}
+
static void wm_gesture_draw_rect(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glBegin(GL_QUADS);
- glVertex2s(rect->xmax, rect->ymin);
- glVertex2s(rect->xmax, rect->ymax);
- glVertex2s(rect->xmin, rect->ymax);
- glVertex2s(rect->xmin, rect->ymin);
- glEnd();
+
+ immUniform4f("color", 1.0f, 1.0f, 1.0f, 0.05f);
+
+ immBegin(GL_QUADS, 4);
+
+ immVertex2f(pos, (float)rect->xmax, (float)rect->ymin);
+ immVertex2f(pos, (float)rect->xmax, (float)rect->ymax);
+ immVertex2f(pos, (float)rect->xmin, (float)rect->ymax);
+ immVertex2f(pos, (float)rect->xmin, (float)rect->ymin);
+
+ immEnd();
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
+
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned line_origin = add_attrib(format, "line_origin", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
+
+ immUniform4f("color1", 0.4f, 0.4f, 0.4f, 1.0f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 8.0f);
+ immUniform1f("dash_width_on", 4.0f);
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xCCCC);
- sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x3333);
- sdrawbox(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ imm_draw_line_box_dashed(pos, line_origin,
+ (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, (float)rect->ymax);
+
+ immUnbindProgram();
+
+ // wm_gesture_draw_line(gt); // draws a diagonal line in the lined box to test wm_gesture_draw_line
}
-static void wm_gesture_draw_line(wmGesture *gt)
+static void imm_draw_lined_dashed_circle(unsigned pos, unsigned line_origin, float x, float y, float rad, int nsegments)
{
- rcti *rect = (rcti *)gt->customdata;
-
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- sdrawline(rect->xmin, rect->ymin, rect->xmax, rect->ymax);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
+ float xpos, ypos;
+
+ xpos = x + rad;
+ ypos = y;
+
+ immBegin(PRIM_LINES, nsegments * 2);
+
+ for (int i = 1; i <= nsegments; ++i) {
+ float angle = 2 * M_PI * ((float)i / (float)nsegments);
+
+ immAttrib2f(line_origin, xpos, ypos);
+ immVertex2f(pos, xpos, ypos);
+
+ xpos = x + rad * cosf(angle);
+ ypos = y + rad * sinf(angle);
+
+ immVertex2f(pos, xpos, ypos);
+ }
+
+ immEnd();
}
static void wm_gesture_draw_circle(wmGesture *gt)
{
rcti *rect = (rcti *)gt->customdata;
- glTranslatef((float)rect->xmin, (float)rect->ymin, 0.0f);
-
glEnable(GL_BLEND);
- glColor4f(1.0, 1.0, 1.0, 0.05);
- glutil_draw_filled_arc(0.0, M_PI * 2.0, rect->xmax, 40);
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ immUniformColor4f(1.0, 1.0, 1.0, 0.05);
+ imm_draw_filled_circle(pos, (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40);
+
+ immUnbindProgram();
+
glDisable(GL_BLEND);
- // for USE_GLSL works bad because of no relation between lines
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, rect->xmax, 40);
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- glutil_draw_lined_arc(0.0, M_PI * 2.0, rect->xmax, 40);
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
- glTranslatef(-rect->xmin, -rect->ymin, 0.0f);
+ format = immVertexFormat();
+ pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned line_origin = add_attrib(format, "line_origin", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
+
+ immUniform4f("color1", 0.4f, 0.4f, 0.4f, 1.0f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 4.0f);
+ immUniform1f("dash_width_on", 2.0f);
+ imm_draw_lined_dashed_circle(pos, line_origin,
+ (float)rect->xmin, (float)rect->ymin, (float)rect->xmax, 40);
+
+ immUnbindProgram();
}
struct LassoFillData {
@@ -253,6 +339,7 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
int i;
rcti rect;
rcti rect_win;
+ float red[4] = {1.0f, 0.0f, 0.0f, 0.0f};
for (i = 0; i < tot; i++, lasso += 2) {
moves[i][0] = lasso[0];
@@ -278,28 +365,28 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
(const int (*)[2])moves, tot,
draw_filled_lasso_px_cb, &lasso_fill_data);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ /* Additive Blending */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
- glColor4f(1, 1, 1, 1);
- glPixelTransferf(GL_RED_BIAS, 1);
- glPixelTransferf(GL_GREEN_BIAS, 1);
- glPixelTransferf(GL_BLUE_BIAS, 1);
+ GLint unpack_alignment;
+ glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack_alignment);
- GPU_basic_shader_bind(GPU_SHADER_TEXTURE_2D | GPU_SHADER_USE_COLOR);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glEnable(GL_BLEND);
- glaDrawPixelsTex(rect.xmin, rect.ymin, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf);
- glDisable(GL_BLEND);
+ GPUShader *shader = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
+ GPU_shader_bind(shader);
+ GPU_shader_uniform_vector(shader, GPU_shader_get_uniform(shader, "shuffle"), 4, 1, red);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ immDrawPixelsTex(rect.xmin, rect.ymin, w, h, GL_RED, GL_UNSIGNED_BYTE, GL_NEAREST, pixel_buf, 1.0f, 1.0f, NULL);
- glPixelTransferf(GL_RED_BIAS, 0);
- glPixelTransferf(GL_GREEN_BIAS, 0);
- glPixelTransferf(GL_BLUE_BIAS, 0);
+ GPU_shader_unbind();
- glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment);
MEM_freeN(pixel_buf);
+
+ glDisable(GL_BLEND);
}
MEM_freeN(moves);
@@ -309,35 +396,57 @@ static void draw_filled_lasso(wmWindow *win, wmGesture *gt)
static void wm_gesture_draw_lasso(wmWindow *win, wmGesture *gt, bool filled)
{
const short *lasso = (short *)gt->customdata;
- int i;
+ int i, numverts;
+ float x, y;
if (filled) {
draw_filled_lasso(win, gt);
}
- // for USE_GLSL can't check this yet
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xAAAA);
- glBegin(GL_LINE_STRIP);
- for (i = 0; i < gt->points; i++, lasso += 2)
- glVertex2sv(lasso);
- if (gt->type == WM_GESTURE_LASSO)
- glVertex2sv((short *)gt->customdata);
- glEnd();
-
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x5555);
- glBegin(GL_LINE_STRIP);
- lasso = (short *)gt->customdata;
- for (i = 0; i < gt->points; i++, lasso += 2)
- glVertex2sv(lasso);
- if (gt->type == WM_GESTURE_LASSO)
- glVertex2sv((short *)gt->customdata);
- glEnd();
-
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
-
+ numverts = gt->points;
+ if (gt->type == WM_GESTURE_LASSO) {
+ numverts++;
+ }
+
+ /* Nothing to drawe, do early output. */
+ if (numverts < 2) {
+ return;
+ }
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned line_origin = add_attrib(format, "line_origin", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
+
+ immUniform4f("color1", 0.4f, 0.4f, 0.4f, 1.0f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 2.0f);
+ immUniform1f("dash_width_on", 1.0f);
+
+ immBegin(PRIM_LINE_STRIP, numverts);
+
+ for (i = 0; i < gt->points; i++, lasso += 2) {
+
+ /* get line_origin coordinates only from the first vertex of each line */
+ if (!(i % 2)) {
+ x = (float)lasso[0];
+ y = (float)lasso[1];
+ }
+
+ immAttrib2f(line_origin, x, y);
+ immVertex2f(pos, (float)lasso[0], (float)lasso[1]);
+ }
+
+ if (gt->type == WM_GESTURE_LASSO) {
+ immAttrib2f(line_origin, x, y);
+ lasso = (short *)gt->customdata;
+ immVertex2f(pos, (float)lasso[0], (float)lasso[1]);
+ }
+
+ immEnd();
+
+ immUnbindProgram();
}
static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
@@ -346,25 +455,52 @@ static void wm_gesture_draw_cross(wmWindow *win, wmGesture *gt)
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
- GPU_basic_shader_bind(GPU_SHADER_LINE | GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR);
- glColor3ub(96, 96, 96);
- GPU_basic_shader_line_stipple(1, 0xCCCC);
- sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
-
- glColor3ub(255, 255, 255);
- GPU_basic_shader_line_stipple(1, 0x3333);
- sdrawline(rect->xmin - winsize_x, rect->ymin, rect->xmin + winsize_x, rect->ymin);
- sdrawline(rect->xmin, rect->ymin - winsize_y, rect->xmin, rect->ymin + winsize_y);
- GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
+ float x1, x2, y1, y2;
+
+ VertexFormat *format = immVertexFormat();
+ unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+ unsigned line_origin = add_attrib(format, "line_origin", COMP_F32, 2, KEEP_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_COLOR);
+
+ immUniform4f("color1", 0.4f, 0.4f, 0.4f, 1.0f);
+ immUniform4f("color2", 1.0f, 1.0f, 1.0f, 1.0f);
+ immUniform1f("dash_width", 8.0f);
+ immUniform1f("dash_width_on", 4.0f);
+
+ immBegin(PRIM_LINES, 4);
+
+ x1 = (float)(rect->xmin - winsize_x);
+ y1 = (float)rect->ymin;
+ x2 = (float)(rect->xmin + winsize_x);
+ y2 = y1;
+
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x1, y1);
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x2, y2);
+
+ x1 = (float)rect->xmin;
+ y1 = (float)(rect->ymin - winsize_y);
+ x2 = x1;
+ y2 = (float)(rect->ymin + winsize_y);
+
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x1, y1);
+ immAttrib2f(line_origin, x1, y1);
+ immVertex2f(pos, x2, y2);
+
+ immEnd();
+
+ immUnbindProgram();
}
/* called in wm_draw.c */
void wm_gesture_draw(wmWindow *win)
{
wmGesture *gt = (wmGesture *)win->gesture.first;
-
- GPU_basic_shader_line_width(1);
+
+ glLineWidth(1.0f);
for (; gt; gt = gt->next) {
/* all in subwindow space */
wmSubWindowSet(win, gt->swinid);
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index fbbde2a6d28..131e216ac8d 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -193,7 +193,7 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_init_reports(C);
/* get the default database, plus a wm */
- wm_homefile_read(C, NULL, G.factory_startup, NULL);
+ wm_homefile_read(C, NULL, G.factory_startup, false, NULL, NULL);
BLT_lang_set(NULL);
@@ -445,8 +445,6 @@ void WM_exit_ext(bContext *C, const bool do_python)
{
wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL;
- BKE_sound_exit();
-
/* first wrap up running stuff, we assume only the active WM is running */
/* modal handlers are on window level freed, others too? */
/* note; same code copied in wm_files.c */
@@ -578,7 +576,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
ED_file_exit(); /* for fsmenu */
UI_exit();
- BKE_blender_userdef_free();
+ BKE_blender_userdef_free_data(&U);
RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */
@@ -595,6 +593,10 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLI_threadapi_exit();
+ /* No need to call this early, rather do it late so that other pieces of Blender using sound may exit cleanly,
+ * see also T50676. */
+ BKE_sound_exit();
+
BKE_blender_atexit();
if (MEM_get_memory_blocks_in_use() != 0) {
diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c
index 4179ac7f993..db5fc23146f 100644
--- a/source/blender/windowmanager/intern/wm_keymap.c
+++ b/source/blender/windowmanager/intern/wm_keymap.c
@@ -121,6 +121,13 @@ static void wm_keymap_item_properties_update_ot(wmKeyMapItem *kmi)
if (ot->srna != kmi->ptr->type) {
/* matches wm_keymap_item_properties_set but doesnt alloc new ptr */
WM_operator_properties_create_ptr(kmi->ptr, ot);
+ /* 'kmi->ptr->data' NULL'd above, keep using existing properties.
+ * Note: the operators property types may have changed,
+ * we will need a more comprehensive sanitize function to support this properly.
+ */
+ if (kmi->properties) {
+ kmi->ptr->data = kmi->properties;
+ }
WM_operator_properties_sanitize(kmi->ptr, 1);
}
}
@@ -1861,10 +1868,6 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
else if (STRPREFIX(opname, "OUTLINER_OT")) {
km = WM_keymap_find_all(C, "Outliner", sl->spacetype, 0);
}
- /* Layer Manager */
- else if (STRPREFIX(opname, "COLLECTIONS_OT")) {
- km = WM_keymap_find_all(C, "Collection Manager", sl->spacetype, 0);
- }
/* Transform */
else if (STRPREFIX(opname, "TRANSFORM_OT")) {
/* check for relevant editor */
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 6591005b5f3..a6f9e84cac3 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -86,9 +86,13 @@
#include "BKE_idcode.h"
-#include "BIF_glutil.h" /* for paint cursor */
#include "BLF_api.h"
+#include "BIF_glutil.h" /* for paint cursor */
+
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -97,9 +101,6 @@
#include "ED_util.h"
#include "ED_view3d.h"
-#include "GPU_basic_shader.h"
-#include "GPU_immediate.h"
-
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -904,7 +905,7 @@ void WM_operator_properties_create_ptr(PointerRNA *ptr, wmOperatorType *ot)
void WM_operator_properties_create(PointerRNA *ptr, const char *opstring)
{
- wmOperatorType *ot = WM_operatortype_find(opstring, 0);
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
if (ot)
WM_operator_properties_create_ptr(ptr, ot);
@@ -1108,45 +1109,70 @@ int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
return WM_menu_invoke_ex(C, op, WM_OP_INVOKE_REGION_WIN);
}
+struct EnumSearchMenu {
+ wmOperator *op; /* the operator that will be executed when selecting an item */
+
+ bool use_previews;
+ short prv_cols, prv_rows;
+};
/* generic enum search invoke popup */
-static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op)
+static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg)
{
- static char search[256] = "";
- wmEvent event;
+ struct EnumSearchMenu *search_menu = arg;
wmWindow *win = CTX_wm_window(C);
+ wmOperator *op = search_menu->op;
+ /* template_ID uses 4 * widget_unit for width, we use a bit more, some items may have a suffix to show */
+ const int width = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_cols : UI_searchbox_size_x();
+ const int height = search_menu->use_previews ? 5 * U.widget_unit * search_menu->prv_rows : UI_searchbox_size_y();
+ static char search[256] = "";
uiBlock *block;
uiBut *but;
- wmOperator *op = (wmOperator *)arg_op;
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ search[0] = '\0';
+ BLI_assert(search_menu->use_previews || (search_menu->prv_cols == 0 && search_menu->prv_rows == 0));
#if 0 /* ok, this isn't so easy... */
uiDefBut(block, UI_BTYPE_LABEL, 0, RNA_struct_ui_name(op->type->srna), 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
#endif
but = uiDefSearchButO_ptr(block, op->type, op->ptr->data, search, 0, ICON_VIEWZOOM, sizeof(search),
- 10, 10, UI_searchbox_size_x(), UI_UNIT_Y, 0, 0, "");
+ 10, 10, width, UI_UNIT_Y, search_menu->prv_rows, search_menu->prv_cols, "");
/* fake button, it holds space for search items */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), UI_searchbox_size_x(), UI_searchbox_size_y(), NULL, 0, 0, 0, 0, NULL);
+ uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 10 - UI_searchbox_size_y(), width, height, NULL, 0, 0, 0, 0, NULL);
UI_block_bounds_set_popup(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */
-
- wm_event_init_from_window(win, &event);
- event.type = EVT_BUT_OPEN;
- event.val = KM_PRESS;
- event.customdata = but;
- event.customdatafree = false;
- wm_event_add(win, &event);
+ UI_but_focus_on_enter_event(win, but);
return block;
}
+/**
+ * Similar to #WM_enum_search_invoke, but draws previews. Also, this can't
+ * be used as invoke callback directly since it needs additional info.
+ */
+int WM_enum_search_invoke_previews(
+ bContext *C, wmOperator *op, short prv_cols, short prv_rows)
+{
+ static struct EnumSearchMenu search_menu;
+
+ search_menu.op = op;
+ search_menu.use_previews = true;
+ search_menu.prv_cols = prv_cols;
+ search_menu.prv_rows = prv_rows;
+
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
+
+ return OPERATOR_INTERFACE;
+}
int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- UI_popup_block_invoke(C, wm_enum_search_menu, op);
+ static struct EnumSearchMenu search_menu;
+ search_menu.op = op;
+ UI_popup_block_invoke(C, wm_enum_search_menu, &search_menu);
return OPERATOR_INTERFACE;
}
@@ -1406,20 +1432,6 @@ static void dialog_exec_cb(bContext *C, void *arg1, void *arg2)
}
}
-static void popup_check_cb(bContext *C, void *op_ptr, void *UNUSED(arg))
-{
- wmOperator *op = op_ptr;
- if (op->type->check) {
- if (op->type->check(C, op)) {
- /* check for popup and re-layout buttons */
- ARegion *ar_menu = CTX_wm_menu(C);
- if (ar_menu) {
- ED_region_tag_refresh_ui(ar_menu);
- }
- }
- }
-}
-
/* Dialogs are popups that require user verification (click OK) before exec */
static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
{
@@ -1438,8 +1450,6 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- UI_block_func_set(block, popup_check_cb, op, NULL);
-
uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE);
/* clear so the OK button is left alone */
@@ -1478,8 +1488,6 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, data->width, data->height, 0, style);
- UI_block_func_set(block, popup_check_cb, op, NULL);
-
/* since ui is defined the auto-layout args are not used */
uiLayoutOperatorButs(C, layout, op, NULL, 'V', 0);
@@ -1526,7 +1534,7 @@ int WM_operator_ui_popup(bContext *C, wmOperator *op, int width, int height)
data->width = width;
data->height = height;
data->free_op = true; /* if this runs and gets registered we may want not to free it */
- UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_operator_ui_create, NULL, wm_operator_ui_popup_cancel, data, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1556,7 +1564,7 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op,
if (!do_redo || !(U.uiflag & USER_GLOBALUNDO))
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
- UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op);
+ UI_popup_block_ex(C, wm_block_create_redo, NULL, wm_block_redo_cancel_cb, op, op);
if (do_call)
wm_block_redo_cb(C, op, 0);
@@ -1598,7 +1606,7 @@ int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, int h
data->free_op = true; /* if this runs and gets registered we may want not to free it */
/* op is not executed until popup OK but is clicked */
- UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data);
+ UI_popup_block_ex(C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op);
return OPERATOR_RUNNING_MODAL;
}
@@ -1765,6 +1773,36 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar
ibuf = IMB_ibImageFromMemory((unsigned char *)datatoc_splash_png,
datatoc_splash_png_size, IB_rect, NULL, "<splash screen>");
}
+
+ /* overwrite splash with template image */
+ if (U.app_template[0] != '\0') {
+ ImBuf *ibuf_template = NULL;
+ char splash_filepath[FILE_MAX];
+ char template_directory[FILE_MAX];
+
+ if (BKE_appdir_app_template_id_search(
+ U.app_template,
+ template_directory, sizeof(template_directory)))
+ {
+ BLI_join_dirfile(
+ splash_filepath, sizeof(splash_filepath), template_directory,
+ (U.pixelsize == 2) ? "splash_2x.png" : "splash.png");
+ ibuf_template = IMB_loadiffname(splash_filepath, IB_rect, NULL);
+ if (ibuf_template) {
+ const int x_expect = ibuf->x;
+ const int y_expect = 230 * (int)U.pixelsize;
+ /* don't cover the header text */
+ if (ibuf_template->x == x_expect && ibuf_template->y == y_expect) {
+ memcpy(ibuf->rect, ibuf_template->rect, ibuf_template->x * ibuf_template->y * sizeof(char[4]));
+ }
+ else {
+ printf("Splash expected %dx%d found %dx%d, ignoring: %s\n",
+ x_expect, y_expect, ibuf_template->x, ibuf_template->y, splash_filepath);
+ }
+ IMB_freeImBuf(ibuf_template);
+ }
+ }
+ }
#endif
block = UI_block_begin(C, ar, "_popup", UI_EMBOSS);
@@ -2079,14 +2117,22 @@ static void WM_OT_window_close(wmOperatorType *ot)
ot->poll = WM_operator_winactive;
}
-static void WM_OT_window_duplicate(wmOperatorType *ot)
+static void WM_OT_window_new(wmOperatorType *ot)
{
- ot->name = "Duplicate Window";
- ot->idname = "WM_OT_window_duplicate";
- ot->description = "Duplicate the current Blender window";
-
- ot->exec = wm_window_duplicate_exec;
+ PropertyRNA *prop;
+
+ ot->name = "New Window";
+ ot->idname = "WM_OT_window_new";
+ ot->description = "Create a new Blender window";
+
+ ot->exec = wm_window_new_exec;
+ ot->invoke = wm_window_new_invoke;
ot->poll = wm_operator_winactive_normal;
+
+ prop = RNA_def_enum(ot->srna, "screen", DummyRNA_NULL_items, 0, "Screen", "");
+ RNA_def_enum_funcs(prop, wm_window_new_screen_itemf);
+ RNA_def_property_flag(prop, PROP_ENUM_NO_TRANSLATE);
+ ot->prop = prop;
}
static void WM_OT_window_fullscreen_toggle(wmOperatorType *ot)
@@ -3047,8 +3093,8 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
/* set up rotation if available */
if (rc->rot_prop) {
rot = RNA_property_float_get(&rc->rot_ptr, rc->rot_prop);
- glPushMatrix();
- glRotatef(RAD2DEGF(rot), 0, 0, 1);
+ gpuPushMatrix();
+ gpuRotate2D(RAD2DEGF(rot));
}
/* draw textured quad */
@@ -3070,7 +3116,7 @@ static void radial_control_paint_tex(RadialControl *rc, float radius, float alph
/* undo rotation */
if (rc->rot_prop)
- glPopMatrix();
+ gpuPopMatrix();
}
else {
/* flat color if no texture available */
@@ -3138,7 +3184,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
/* Keep cursor in the original place */
x = rc->initial_mouse[0] - ar->winrct.xmin;
y = rc->initial_mouse[1] - ar->winrct.ymin;
- glTranslatef((float)x, (float)y, 0.0f);
+ gpuTranslate2f((float)x, (float)y);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
@@ -3146,7 +3192,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
/* apply zoom if available */
if (rc->zoom_prop) {
RNA_property_float_get_array(&rc->zoom_ptr, rc->zoom_prop, zoom);
- glScalef(zoom[0], zoom[1], 1);
+ gpuScale2fv(zoom);
}
/* draw rotated texture */
@@ -3163,23 +3209,23 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
immUniformColor3fvAlpha(col, 0.5);
if (rc->subtype == PROP_ANGLE) {
- glPushMatrix();
+ gpuPushMatrix();
/* draw original angle line */
- glRotatef(RAD2DEGF(rc->initial_value), 0, 0, 1);
+ gpuRotate2D(RAD2DEGF(rc->initial_value));
immBegin(GL_LINES, 2);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
immEnd();
/* draw new angle line */
- glRotatef(RAD2DEGF(rc->current_value - rc->initial_value), 0, 0, 1);
+ gpuRotate2D(RAD2DEGF(rc->current_value - rc->initial_value));
immBegin(GL_LINES, 2);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_MIN_SIZE, 0.0f);
immVertex2f(pos, (float)WM_RADIAL_CONTROL_DISPLAY_SIZE, 0.0f);
immEnd();
- glPopMatrix();
+ gpuPopMatrix();
}
/* draw circles on top */
@@ -3187,6 +3233,7 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
imm_draw_lined_circle(pos, 0.0f, 0.0f, r2, 40);
if (rmin > 0.0f)
imm_draw_lined_circle(pos, 0.0, 0.0f, rmin, 40);
+ immUnbindProgram();
BLF_size(fontid, 1.5 * fstyle_points * U.pixelsize, U.dpi);
BLF_enable(fontid, BLF_SHADOW);
@@ -3203,7 +3250,6 @@ static void radial_control_paint_cursor(bContext *C, int x, int y, void *customd
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
- immUnbindProgram();
}
typedef enum {
@@ -4177,7 +4223,7 @@ void wm_operatortype_init(void)
global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048);
WM_operatortype_append(WM_OT_window_close);
- WM_operatortype_append(WM_OT_window_duplicate);
+ WM_operatortype_append(WM_OT_window_new);
WM_operatortype_append(WM_OT_read_history);
WM_operatortype_append(WM_OT_read_homefile);
WM_operatortype_append(WM_OT_read_factory_settings);
@@ -4419,7 +4465,7 @@ void wm_window_keymap(wmKeyConfig *keyconf)
wmKeyMapItem *kmi;
/* note, this doesn't replace existing keymap items */
- WM_keymap_verify_item(keymap, "WM_OT_window_duplicate", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
+ WM_keymap_verify_item(keymap, "WM_OT_window_new", WKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
#ifdef __APPLE__
WM_keymap_add_item(keymap, "WM_OT_read_homefile", NKEY, KM_PRESS, KM_OSKEY, 0);
WM_keymap_add_menu(keymap, "INFO_MT_file_open_recent", OKEY, KM_PRESS, KM_SHIFT | KM_OSKEY, 0);
diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c
index 6bf7bcc2934..46c7599ec56 100644
--- a/source/blender/windowmanager/intern/wm_playanim.c
+++ b/source/blender/windowmanager/intern/wm_playanim.c
@@ -64,6 +64,8 @@
#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_matrix.h"
+
#include "DNA_scene_types.h"
#include "ED_datafiles.h" /* for fonts */
#include "GHOST_C-api.h"
@@ -190,10 +192,7 @@ static void playanim_window_get_size(int *r_width, int *r_height)
static void playanim_gl_matrix(void)
{
/* unified matrix, note it affects offset for drawing */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
- glMatrixMode(GL_MODELVIEW);
+ gpuOrtho2D(0.0f, 1.0f, 0.0f, 1.0f);
}
/* implementation */
@@ -318,7 +317,7 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- fdrawcheckerboard(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
+ imm_draw_checker_box(offs_x, offs_y, offs_x + span_x, offs_y + span_y);
}
glRasterPos2f(offs_x + (ps->draw_flip[0] ? span_x : 0.0f),
@@ -354,12 +353,12 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
float fac = ps->picture->frame / (double)(((PlayAnimPict *)picsbase.last)->frame - ((PlayAnimPict *)picsbase.first)->frame);
fac = 2.0f * fac - 1.0f;
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION); /* TODO: convert this nasty code */
+ gpuPushMatrix();
+ gpuLoadIdentity();
glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
+ gpuPushMatrix();
+ gpuLoadIdentity();
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
@@ -368,9 +367,9 @@ static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf
glVertex2f(fac, 1.0f);
glEnd();
- glPopMatrix();
+ gpuPopMatrix();
glMatrixMode(GL_PROJECTION);
- glPopMatrix();
+ gpuPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index d312f4c007c..bd22cb191c7 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -52,8 +52,6 @@
#include "ED_screen.h"
-#include "GPU_glew.h"
-#include "GPU_basic_shader.h"
#include "GPU_immediate.h"
#include "WM_api.h"
@@ -396,6 +394,32 @@ bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
return true;
}
+/**
+ * If needed, this adjusts \a r_mouse_xy so that drawn cursor and handled mouse position are matching visually.
+*/
+void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy)
+{
+ if (!WM_stereo3d_enabled(win, false))
+ return;
+
+ if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
+ const int half_x = win->sizex / 2;
+ /* right half of the screen */
+ if (r_mouse_xy[0] > half_x) {
+ r_mouse_xy[0] -= half_x;
+ }
+ r_mouse_xy[0] *= 2;
+ }
+ else if (win->stereo3d_format->display_mode == S3D_DISPLAY_TOPBOTTOM) {
+ const int half_y = win->sizey / 2;
+ /* upper half of the screen */
+ if (r_mouse_xy[1] > half_y) {
+ r_mouse_xy[1] -= half_y;
+ }
+ r_mouse_xy[1] *= 2;
+ }
+}
+
/************************** Stereo 3D operator **********************************/
typedef struct Stereo3dData {
Stereo3dFormat stereo3d_format;
diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c
index 458ac4a121a..d73aa107cab 100644
--- a/source/blender/windowmanager/intern/wm_subwindow.c
+++ b/source/blender/windowmanager/intern/wm_subwindow.c
@@ -47,8 +47,7 @@
#include "BIF_gl.h"
-#include "GPU_extensions.h"
-#include "GPU_basic_shader.h"
+#include "GPU_matrix.h"
#include "WM_api.h"
#include "wm_subwindow.h"
@@ -150,7 +149,7 @@ static void wm_swin_matrix_get(wmWindow *win, wmSubWindow *swin, float mat[4][4]
orthographic_m4(mat, -GLA_PIXEL_OFS, (float)width - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, (float)height - GLA_PIXEL_OFS, -100, 100);
}
else {
- glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat);
+ gpuGetProjectionMatrix3D(mat);
}
}
void wm_subwindow_matrix_get(wmWindow *win, int swinid, float mat[4][4])
@@ -216,7 +215,7 @@ int wm_subwindow_open(wmWindow *win, const rcti *winrct, bool activate)
/* extra service */
wm_swin_size_get(swin, &width, &height);
wmOrtho2_pixelspace(width, height);
- glLoadIdentity();
+ gpuLoadIdentity();
}
return swin->swinid;
@@ -322,7 +321,7 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, const rcti *srct, bool src
glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
wmOrtho2_pixelspace(width, height);
- glLoadIdentity();
+ gpuLoadIdentity();
glFlush();
}
@@ -333,31 +332,13 @@ void wmSubWindowSet(wmWindow *win, int swinid)
wmSubWindowScissorSet(win, swinid, NULL, true);
}
-void wmFrustum(float x1, float x2, float y1, float y2, float n, float f)
-{
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glFrustum(x1, x2, y1, y2, n, f);
- glMatrixMode(GL_MODELVIEW);
-}
-
-void wmOrtho(float x1, float x2, float y1, float y2, float n, float f)
-{
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glOrtho(x1, x2, y1, y2, n, f);
-
- glMatrixMode(GL_MODELVIEW);
-}
-
void wmOrtho2(float x1, float x2, float y1, float y2)
{
/* prevent opengl from generating errors */
if (x1 == x2) x2 += 1.0f;
if (y1 == y2) y2 += 1.0f;
- wmOrtho(x1, x2, y1, y2, -100, 100);
+ gpuOrtho(x1, x2, y1, y2, -100, 100);
}
static void wmOrtho2_offset(const float x, const float y, const float ofs)
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index e271225e437..2027afef103 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -58,6 +58,7 @@
#include "RNA_access.h"
+#include "RNA_define.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -71,6 +72,7 @@
#include "ED_fileselect.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "PIL_time.h"
@@ -78,6 +80,9 @@
#include "GPU_extensions.h"
#include "GPU_init_exit.h"
#include "GPU_immediate.h"
+#include "BLF_api.h"
+
+#include "UI_resources.h"
/* for assert */
#ifndef NDEBUG
@@ -244,6 +249,25 @@ wmWindow *wm_window_new(bContext *C)
return win;
}
+/**
+ * A higher level version of copy that tests the new window can be added.
+ */
+static wmWindow *wm_window_new_test(bContext *C)
+{
+ wmWindow *win = wm_window_new(C);
+
+ WM_check(C);
+
+ if (win->ghostwin) {
+ WM_event_add_notifier(C, NC_WINDOW | NA_ADDED, NULL);
+ return win;
+ }
+ else {
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm_window_close(C, wm, win);
+ return NULL;
+ }
+}
/* part of wm_window.c api */
wmWindow *wm_window_copy(bContext *C, wmWindow *win_src)
@@ -312,7 +336,7 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
if (tmpwin == NULL)
do_exit = 1;
- if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved) {
+ if ((U.uiflag & USER_QUIT_PROMPT) && !wm->file_saved && !G.background) {
if (do_exit) {
if (!GHOST_confirmQuit(win->ghostwin))
return;
@@ -375,14 +399,39 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
}
-static float wm_window_get_virtual_pixelsize(void)
+static void wm_window_set_dpi(wmWindow *win)
{
- return ((U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1.0f : 2.0f);
-}
+ int auto_dpi = GHOST_GetDPIHint(win->ghostwin);
-float wm_window_pixelsize(wmWindow *win)
-{
- return (GHOST_GetNativePixelSize(win->ghostwin) * wm_window_get_virtual_pixelsize());
+ /* Lazily init UI scale size, preserving backwards compatibility by
+ * computing UI scale from ratio of previous DPI and auto DPI */
+ if (U.ui_scale == 0) {
+ int virtual_pixel = (U.virtual_pixel == VIRTUAL_PIXEL_NATIVE) ? 1 : 2;
+
+ if (U.dpi == 0) {
+ U.ui_scale = virtual_pixel;
+ }
+ else {
+ U.ui_scale = (virtual_pixel * U.dpi * 96.0f) / (auto_dpi * 72.0f);
+ }
+
+ CLAMP(U.ui_scale, 0.25f, 4.0f);
+ }
+
+ /* Blender's UI drawing assumes DPI 72 as a good default following macOS
+ * while Windows and Linux use DPI 96. GHOST assumes a default 96 so we
+ * remap the DPI to Blender's convention. */
+ int dpi = auto_dpi * U.ui_scale * (72.0 / 96.0f);
+
+ /* Automatically set larger pixel size for high DPI. */
+ int pixelsize = MAX2(1, dpi / 54);
+
+ /* Set user preferences globals for drawing, and for forward compatibility. */
+ U.pixelsize = GHOST_GetNativePixelSize(win->ghostwin) * pixelsize;
+ U.dpi = dpi / pixelsize;
+ U.virtual_pixel = (pixelsize == 1) ? VIRTUAL_PIXEL_NATIVE : VIRTUAL_PIXEL_DOUBLE;
+
+ BKE_blender_userdef_refresh();
}
/* belongs to below */
@@ -457,10 +506,8 @@ static void wm_window_ghostwindow_add(wmWindowManager *wm, const char *title, wm
glClear(GL_COLOR_BUFFER_BIT);
}
- /* displays with larger native pixels, like Macbook. Used to scale dpi with */
/* needed here, because it's used before it reads userdef */
- U.pixelsize = wm_window_pixelsize(win);
- BKE_blender_userdef_refresh();
+ wm_window_set_dpi(win);
wm_window_swap_buffers(win);
@@ -627,7 +674,6 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type)
Scene *scene = CTX_data_scene(C);
const char *title;
rcti rect = *rect_init;
- const short px_virtual = (short)wm_window_get_virtual_pixelsize();
/* changes rect to fit within desktop */
wm_window_check_position(&rect);
@@ -645,9 +691,8 @@ wmWindow *WM_window_open_temp(bContext *C, const rcti *rect_init, int type)
win->posy = rect.ymin;
}
- /* multiply with virtual pixelsize, ghost handles native one (e.g. for retina) */
- win->sizex = BLI_rcti_size_x(&rect) * px_virtual;
- win->sizey = BLI_rcti_size_y(&rect) * px_virtual;
+ win->sizex = BLI_rcti_size_x(&rect);
+ win->sizey = BLI_rcti_size_y(&rect);
if (win->ghostwin) {
wm_window_set_size(win, win->sizex, win->sizey);
@@ -723,17 +768,79 @@ int wm_window_close_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-/* operator callback */
-int wm_window_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
+/* new window operator callback */
+int wm_window_new_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
wmWindow *win_src = CTX_wm_window(C);
- bool ok;
+ const int screen_id = RNA_enum_get(op->ptr, "screen");
+ bScreen *screen = BLI_findlink(&bmain->screen, screen_id);
+ wmWindow *win_dst;
- ok = (wm_window_copy_test(C, win_src) != NULL);
+ if (screen->winid) {
+ /* Screen is already used, duplicate window and screen */
+ win_dst = wm_window_copy_test(C, win_src);
+ }
+ else if ((win_dst = wm_window_new_test(C))) {
+ /* New window with a different screen */
+ win_dst->screen = screen;
+ screen->winid = win_dst->winid;
+ CTX_wm_window_set(C, win_dst);
+ ED_screen_refresh(CTX_wm_manager(C), win_dst);
+ }
- return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+ return (win_dst != NULL) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
+int wm_window_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Main *bmain = CTX_data_main(C);
+
+ if (BLI_listbase_count_ex(&bmain->screen, 2) == 1) {
+ RNA_enum_set(op->ptr, "screen", 0);
+ return wm_window_new_exec(C, op);
+ }
+ else {
+ return WM_enum_search_invoke_previews(C, op, 6, 2);
+ }
+}
+
+struct EnumPropertyItem *wm_window_new_screen_itemf(
+ bContext *C, struct PointerRNA *UNUSED(ptr), struct PropertyRNA *UNUSED(prop), bool *r_free)
+{
+ Main *bmain = CTX_data_main(C);
+ EnumPropertyItem *item = NULL;
+ EnumPropertyItem tmp = {0, "", 0, "", ""};
+ int value = 0, totitem = 0;
+ int count_act_screens = 0;
+ /* XXX setting max number of windows to 20. We'd need support
+ * for dynamic strings in EnumPropertyItem.name to avoid this. */
+ static char active_screens[20][MAX_NAME + 12];
+
+ for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
+ if (screen->winid) {
+ BLI_snprintf(active_screens[count_act_screens], sizeof(*active_screens), "%s (Duplicate)",
+ screen->id.name + 2);
+ tmp.name = active_screens[count_act_screens++];
+ }
+ else {
+ tmp.name = screen->id.name + 2;
+ }
+
+ tmp.value = value;
+ tmp.identifier = screen->id.name;
+ UI_id_icon_render(C, CTX_data_scene(C), &screen->id, true, false);
+ tmp.icon = BKE_icon_id_ensure(&screen->id);
+
+ RNA_enum_item_add(&item, &totitem, &tmp);
+ value++;
+ }
+
+ RNA_enum_item_end(&item, &totitem);
+ *r_free = true;
+
+ return item;
+}
/* fullscreen operator callback */
int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
@@ -828,7 +935,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
{
if (win != wm->windrawable && win->ghostwin) {
// win->lmbut = 0; /* keeps hanging when mousepressed while other window opened */
-
+
wm->windrawable = win;
if (G.debug & G_DEBUG_EVENTS) {
printf("%s: set drawable %d\n", __func__, win->winid);
@@ -839,8 +946,7 @@ void wm_window_make_drawable(wmWindowManager *wm, wmWindow *win)
immActivate();
/* this can change per window */
- U.pixelsize = wm_window_pixelsize(win);
- BKE_blender_userdef_refresh();
+ wm_window_set_dpi(win);
}
}
@@ -1039,6 +1145,8 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
if (type == GHOST_kEventWindowSize) {
WM_jobs_stop(wm, win->screen, NULL);
}
+
+ wm_window_set_dpi(win);
/* win32: gives undefined window size when minimized */
if (state != GHOST_kWindowStateMinimized) {
@@ -1123,7 +1231,19 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
}
break;
}
-
+
+ case GHOST_kEventWindowDPIHintChanged:
+ {
+ wm_window_set_dpi(win);
+ /* font's are stored at each DPI level, without this we can easy load 100's of fonts */
+ BLF_cache_clear();
+
+ BKE_blender_userdef_refresh();
+ WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL); /* refresh region sizes */
+ break;
+ }
+
case GHOST_kEventOpenMainFile:
{
PointerRNA props_ptr;
@@ -1204,10 +1324,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
{
// only update if the actual pixel size changes
float prev_pixelsize = U.pixelsize;
- U.pixelsize = wm_window_pixelsize(win);
+ wm_window_set_dpi(win);
if (U.pixelsize != prev_pixelsize) {
- BKE_blender_userdef_refresh();
BKE_icon_changed(win->screen->id.icon_id);
// close all popups since they are positioned with the pixel
diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c b/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c
index ae3febfc2d1..d526f754d51 100644
--- a/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/arrow_manipulator.c
@@ -42,6 +42,7 @@
#include "RNA_types.h"
#include "WM_types.h"
+#include "WM_api.h"
#include "manipulator_geometry.h"
#include "manipulator_library_intern.h"
@@ -130,7 +131,7 @@ static void arrow_draw_geom(const ArrowManipulator *arrow, const float col[4], c
const float len = arrow->length;
const bool use_lighting = /*select == false && ((U.manipulator_flag & V3D_SHADED_MANIPULATORS) != 0)*/ false;
- glTranslate3fv(arrow->manipulator.offset);
+ glTranslatef(UNPACK3(arrow->manipulator.offset));
arrow_draw_line(arrow, col, len);
@@ -173,7 +174,7 @@ static void arrow_draw_intern(const ArrowManipulator *arrow, const bool select,
arrow_get_matrix(arrow, rot, mat);
glPushMatrix();
- glMultMatrixf(mat);
+ glMultMatrixf((float *)mat);
glEnable(GL_BLEND);
arrow_draw_geom(arrow, col, select);
@@ -190,7 +191,7 @@ static void arrow_draw_intern(const ArrowManipulator *arrow, const bool select,
mul_mat3_m4_fl(mat, inter->init_scale);
glPushMatrix();
- glMultMatrixf(mat);
+ glMultMatrixf((float *)mat);
glEnable(GL_BLEND);
arrow_draw_geom(arrow, ghost_col, select);
diff --git a/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c b/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c
index ffc38371d7d..908471ec728 100644
--- a/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c
+++ b/source/blender/windowmanager/manipulators/intern/manipulator_library/dial_manipulator.c
@@ -96,7 +96,7 @@ static void dial_geom_draw(
if (use_clipping) {
glEnable(GL_CLIP_DISTANCE0);
immUniform4fv("ClipPlane", clipping_plane);
- immUniformMat4("ModelMatrix", mat);
+ immUniformMatrix4fv("ModelMatrix", mat);
}
if (filled) {
@@ -117,7 +117,6 @@ static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[
immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
immUniformColor4fv(col);
- gpuMatrixBegin3D_legacy();
gpuPushMatrix();
gpuRotateAxis(-RAD2DEGF(angle), 'Z');
@@ -127,7 +126,6 @@ static void dial_ghostarc_draw_helpline(const float angle, const float co_outer[
immEnd();
gpuPopMatrix();
- gpuMatrixEnd();
immUnbindProgram();
}
@@ -197,7 +195,7 @@ static void dial_draw_intern(const bContext *C, DialManipulator *dial, const boo
}
glPushMatrix();
- glMultMatrixf(mat);
+ glMultMatrixf((float *)mat);
if (use_value_indicator) {
const float col_inner[] = {0.8f, 0.8f, 0.8f, 0.4f};
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
index cfdc085e7e4..d435130927e 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulator_intern.h
@@ -35,7 +35,7 @@ struct wmManipulatorMap;
/* wmManipulator */
/* manipulators are set per region by registering them on manipulator-maps */
-typedef struct wmManipulator {
+struct wmManipulator {
struct wmManipulator *next, *prev;
char idname[MAX_NAME + 4]; /* + 4 for unique '.001', '.002', etc suffix */
@@ -106,7 +106,7 @@ typedef struct wmManipulator {
* the manipulator is interacted with, those properties get updated */
PointerRNA *ptr;
PropertyRNA **props;
-} wmManipulator;
+};
/* wmManipulator.state */
enum {
@@ -170,7 +170,7 @@ void wm_manipulatorgrouptype_keymap_init(struct wmManipulatorGroupType *mgroupty
/* -------------------------------------------------------------------- */
/* wmManipulatorMap */
-typedef struct wmManipulatorMap {
+struct wmManipulatorMap {
struct wmManipulatorMap *next, *prev;
struct wmManipulatorMapType *type;
@@ -194,7 +194,7 @@ typedef struct wmManipulatorMap {
struct wmManipulator **selected_manipulator;
int tot_selected;
} mmap_context;
-} wmManipulatorMap;
+};
/**
* This is a container for all manipulator types that can be instantiated in a region.
@@ -202,13 +202,13 @@ typedef struct wmManipulatorMap {
*
* \note There is only ever one of these for every (area, region) combination.
*/
-typedef struct wmManipulatorMapType {
+struct wmManipulatorMapType {
struct wmManipulatorMapType *next, *prev;
char idname[64];
short spaceid, regionid;
/* types of manipulator-groups for this manipulator-map type */
ListBase manipulator_grouptypes;
-} wmManipulatorMapType;
+};
void wm_manipulatormap_selected_delete(wmManipulatorMap *mmap);
bool wm_manipulatormap_deselect_all(struct wmManipulatorMap *mmap, wmManipulator ***sel);
diff --git a/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
index 960a77fd74c..303a625fc23 100644
--- a/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
+++ b/source/blender/windowmanager/manipulators/intern/wm_manipulatormap.c
@@ -279,35 +279,32 @@ static int manipulator_find_intersected_3D_intern(
ARegion *ar = CTX_wm_region(C);
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
- rctf rect, selrect;
+ rcti rect;
GLuint buffer[64]; // max 4 items per select, so large enuf
short hits;
const bool do_passes = GPU_select_query_check_active();
- extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, rctf *rect);
-
+ extern void view3d_winmatrix_set(ARegion *ar, View3D *v3d, const rcti *rect);
rect.xmin = co[0] - hotspot;
rect.xmax = co[0] + hotspot;
rect.ymin = co[1] - hotspot;
rect.ymax = co[1] + hotspot;
- selrect = rect;
-
view3d_winmatrix_set(ar, v3d, &rect);
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
if (do_passes)
- GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
else
- GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_ALL, 0);
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_ALL, 0);
/* do the drawing */
manipulator_find_active_3D_loop(C, visible_manipulators);
hits = GPU_select_end();
if (do_passes) {
- GPU_select_begin(buffer, ARRAY_SIZE(buffer), &selrect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
+ GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
manipulator_find_active_3D_loop(C, visible_manipulators);
GPU_select_end();
}
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 3dd294128e2..f63246580ea 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -80,6 +80,7 @@ void wm_autosave_location(char *filepath);
/* wm_stereo.c */
void wm_method_draw_stereo3d(const bContext *C, wmWindow *win);
+void wm_stereo3d_mouse_offset_apply(wmWindow *win, int *r_mouse_xy);
int wm_stereo3d_set_exec(bContext *C, wmOperator *op);
int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event);
void wm_stereo3d_set_draw(bContext *C, wmOperator *op);
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index 396907a3f6d..9a1518e15b0 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -35,7 +35,10 @@ struct wmOperatorType;
/* wm_files.c */
void wm_history_file_read(void);
-int wm_homefile_read(struct bContext *C, struct ReportList *reports, bool from_memory, const char *filepath);
+int wm_homefile_read(
+ struct bContext *C, struct ReportList *reports,
+ bool use_factory_settings, bool use_empty_data,
+ const char *filepath_startup_override, const char *app_template_override);
void wm_file_read_report(bContext *C);
void WM_OT_save_homefile(struct wmOperatorType *ot);
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index c106f9d7851..089e2994d3d 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -32,7 +32,11 @@
#ifndef __WM_WINDOW_H__
#define __WM_WINDOW_H__
+struct EnumPropertyItem;
+struct wmEvent;
struct wmOperator;
+struct PointerRNA;
+struct PropertyRNA;
/* *************** internal api ************** */
void wm_ghost_init (bContext *C);
@@ -63,8 +67,6 @@ void wm_window_swap_buffers (wmWindow *win);
void wm_window_set_swap_interval(wmWindow *win, int interval);
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
-float wm_window_pixelsize(wmWindow *win);
-
void wm_get_cursor_position (wmWindow *win, int *x, int *y);
void wm_cursor_position_from_ghost (wmWindow *win, int *x, int *y);
void wm_cursor_position_to_ghost (wmWindow *win, int *x, int *y);
@@ -78,9 +80,12 @@ void wm_window_IME_end (wmWindow *win);
/* *************** window operators ************** */
int wm_window_close_exec(bContext *C, struct wmOperator *op);
-int wm_window_duplicate_exec(bContext *C, struct wmOperator *op);
int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op);
+struct EnumPropertyItem *wm_window_new_screen_itemf(bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free);
+int wm_window_new_exec(bContext *C, struct wmOperator *op);
+int wm_window_new_invoke(bContext *C, struct wmOperator *op, const struct wmEvent *event);
+
/* Initial (unmaximized) size to start with for
* systems that can't find it for themselves (X11).
* Clamped by real desktop limits */
diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt
index 58bebc66a3e..82e80634b87 100644
--- a/source/blenderplayer/CMakeLists.txt
+++ b/source/blenderplayer/CMakeLists.txt
@@ -138,6 +138,7 @@ endif()
bf_intern_moto
bf_nodes
bf_gpu
+ bf_intern_gawain
bf_imbuf
bf_avi
ge_logic_network
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 0acc66ad9b0..66b7f23c2f9 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -310,6 +310,7 @@ int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct
struct MenuType *WM_menutype_find(const char *idname, bool quiet) RET_NULL
void WM_operator_stack_clear(struct wmWindowManager *wm) RET_NONE
void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot) RET_NONE
+bool WM_operator_is_repeat(const struct bContext *C, const struct wmOperator *op) RET_ZERO;
void WM_autosave_init(wmWindowManager *wm) RET_NONE
void WM_jobs_kill_all_except(struct wmWindowManager *wm, void *owner) RET_NONE
@@ -413,7 +414,7 @@ void ED_fsmenu_entry_set_path(struct FSMenuEntry *fsentry, const char *name) RET
char *ED_fsmenu_entry_get_name(struct FSMenuEntry *fsentry) RET_NULL
void ED_fsmenu_entry_set_name(struct FSMenuEntry *fsentry, const char *name) RET_NONE
-struct PTCacheEdit *PE_get_current(struct Scene *scene, struct Object *ob) RET_NULL
+struct PTCacheEdit *PE_get_current(struct Scene *scene, struct SceneLayer *sl, struct Object *ob) RET_NULL
void PE_current_changed(struct Scene *scene, struct Object *ob) RET_NONE
/* rna keymap */
@@ -535,7 +536,7 @@ int ED_mesh_mirror_spatial_table(struct Object *ob, struct BMEditMesh *em, struc
float ED_rollBoneToVector(EditBone *bone, const float new_up_axis[3], const bool axis_only) RET_ZERO
void ED_space_image_get_size(struct SpaceImage *sima, int *width, int *height) RET_NONE
-bool ED_space_image_check_show_maskedit(struct Scene *scene, struct SpaceImage *sima) RET_ZERO
+bool ED_space_image_check_show_maskedit(struct SceneLayer *sl, struct SpaceImage *sima) RET_ZERO
bool ED_texture_context_check_world(const struct bContext *C) RET_ZERO
bool ED_texture_context_check_material(const struct bContext *C) RET_ZERO
@@ -599,6 +600,12 @@ const char *uiLayoutIntrospect(uiLayout *layout) RET_NULL
void UI_reinit_font(void) RET_NONE
int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big) RET_ZERO
struct bTheme *UI_GetTheme(void) RET_NULL
+void UI_GetThemeColor4fv(int colorid, float col[4]) RET_NONE
+void UI_GetThemeColorShade4fv(int colorid, int offset, float col[4]) RET_NONE
+void UI_GetThemeColorShadeAlpha4fv(int colorid, int coloffset, int alphaoffset, float col[4]) RET_NONE
+void UI_GetThemeColorBlendShade4fv(int colorid1, int colorid2, float fac, int offset, float col[4]) RET_NONE
+void UI_GetThemeColorBlend3ubv(int colorid1, int colorid2, float fac, unsigned char col[3]) RET_NONE
+void UI_GetThemeColorShadeAlpha4ubv(int colorid, int coloffset, int alphaoffset, unsigned char col[4]) RET_NONE
/* rna template */
void uiTemplateAnyID(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) RET_NONE
@@ -632,6 +639,7 @@ void uiTemplateNodeView(struct uiLayout *layout, struct bContext *C, struct bNod
void uiTemplateTextureUser(struct uiLayout *layout, struct bContext *C) RET_NONE
void uiTemplateTextureShow(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) RET_NONE
void uiTemplateKeymapItemProperties(struct uiLayout *layout, struct PointerRNA *ptr) RET_NONE
+void uiTemplateOverrideProperty(struct uiLayout *layout, struct PointerRNA *collection_props_ptr, struct PointerRNA *scene_props_ptr, const char *name, const char *custom_template) RET_NONE
void uiTemplateMovieClip(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, int compact) RET_NONE
void uiTemplateMovieclipInformation(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname, struct PointerRNA *userptr) RET_NONE
void uiTemplateTrack(struct uiLayout *layout, struct PointerRNA *ptr, const char *propname) RET_NONE
@@ -682,7 +690,10 @@ void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
/* Draw */
-void *DRW_render_settings_get(struct Scene *scene, const char *engine_name) RET_NULL
+void OBJECT_collection_settings_create(struct IDProperty *properties) RET_NONE
+void EDIT_MESH_collection_settings_create(struct IDProperty *properties) RET_NONE
+void EDIT_ARMATURE_collection_settings_create(struct IDProperty *properties) RET_NONE
+void DRW_object_engine_data_free(struct Object *ob) RET_NONE
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
@@ -725,6 +736,7 @@ int UI_pie_menu_invoke_from_operator_enum(struct bContext *C, const char *title,
/* RNA COLLADA dependency */
int collada_export(struct Scene *sce,
+ struct SceneLayer *scene_layer,
const char *filepath,
int apply_modifiers,
BC_export_mesh_type export_mesh_type,
@@ -745,7 +757,9 @@ int collada_export(struct Scene *sce,
int use_blender_profile,
int sort_by_name,
BC_export_transformation_type export_transformation_type,
- int open_sim) RET_ZERO
+ int open_sim,
+ int limit_precision,
+ int keep_bind_info) RET_ZERO
void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly) RET_NONE
@@ -788,7 +802,4 @@ void COM_execute(RenderData *rd, Scene *scene, bNodeTree *editingtree, int rende
bool RE_RenderResult_is_stereo(RenderResult *res) RET_ZERO
void uiTemplateImageViews(uiLayout *layout, struct PointerRNA *imfptr) RET_NONE
-/* GPU */
-void immBindBuiltinProgram(GPUBuiltinShader shader_id) RET_NONE
-
#endif // WITH_GAMEENGINE
diff --git a/source/creator/creator_args.c b/source/creator/creator_args.c
index 3b6cd1c9561..3850846b0b9 100644
--- a/source/creator/creator_args.c
+++ b/source/creator/creator_args.c
@@ -943,7 +943,7 @@ static int arg_handle_native_pixels_set(int UNUSED(argc), const char **UNUSED(ar
}
static const char arg_handle_with_borders_doc[] =
-"\n\tForce opening without borders"
+"\n\tForce opening with borders"
;
static int arg_handle_with_borders(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
{
@@ -1182,16 +1182,6 @@ static int arg_handle_threads_set(int argc, const char **argv, void *UNUSED(data
}
}
-static const char arg_handle_basic_shader_use_legacy_doc[] =
-"\n\tUse legacy (non-GLSL) basic shader"
-;
-static int arg_handle_basic_shader_use_legacy(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
-{
- printf("Using legacy (non-GLSL) basic shader.\n");
- GPU_basic_shader_use_glsl_set(false);
- return 0;
-}
-
static const char arg_handle_verbosity_set_doc[] =
"<verbose>\n"
"\tSet logging verbosity level."
@@ -1351,7 +1341,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
re = RE_NewRender(scene->id.name);
BLI_begin_threaded_malloc();
- BKE_reports_init(&reports, RPT_PRINT);
+ BKE_reports_init(&reports, RPT_STORE);
RE_SetReports(re, &reports);
for (int i = 0; i < frames_range_len; i++) {
@@ -1366,6 +1356,7 @@ static int arg_handle_render_frame(int argc, const char **argv, void *data)
}
}
RE_SetReports(re, NULL);
+ BKE_reports_clear(&reports);
BLI_end_threaded_malloc();
MEM_freeN(frame_range_arr);
return 1;
@@ -1393,10 +1384,11 @@ static int arg_handle_render_animation(int UNUSED(argc), const char **UNUSED(arg
Render *re = RE_NewRender(scene->id.name);
ReportList reports;
BLI_begin_threaded_malloc();
- BKE_reports_init(&reports, RPT_PRINT);
+ BKE_reports_init(&reports, RPT_STORE);
RE_SetReports(re, &reports);
RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
RE_SetReports(re, NULL);
+ BKE_reports_clear(&reports);
BLI_end_threaded_malloc();
}
else {
@@ -1827,8 +1819,6 @@ void main_args_setup(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
BLI_argsAdd(ba, 1, NULL, "--debug-gpumem",
CB_EX(arg_handle_debug_mode_generic_set, gpumem), (void *)G_DEBUG_GPU_MEM);
- BLI_argsAdd(ba, 1, NULL, "--enable-legacy-basic-shader", CB(arg_handle_basic_shader_use_legacy), NULL);
-
BLI_argsAdd(ba, 1, NULL, "--verbose", CB(arg_handle_verbosity_set), NULL);
BLI_argsAdd(ba, 1, NULL, "--factory-startup", CB(arg_handle_factory_startup_set), NULL);
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
index d7fe8d8ce59..6c3751ae34d 100644
--- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
+++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp
@@ -104,13 +104,13 @@ typedef void * wmUIHandlerRemoveFunc;
# include AUD_DEVICE_H
#endif
-static BlendFileData *load_game_data(char *filename)
+static BlendFileData *load_game_data(const char *filename)
{
ReportList reports;
BlendFileData *bfd;
BKE_reports_init(&reports, RPT_STORE);
- bfd= BLO_read_from_file(filename, &reports);
+ bfd= BLO_read_from_file(filename, &reports, BLO_READ_SKIP_USERDEF);
if (!bfd) {
printf("Loading %s failed: ", filename);
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 2aa0145d1f3..6add30f1131 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -394,7 +394,7 @@ static void SetDefaultLightMode(Scene* scene)
{
default_light_mode = false;
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
for (SETLOOPER(scene, sce_iter, base))
{
@@ -1736,7 +1736,7 @@ static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, u
static void blenderSceneSetBackground(Scene *blenderscene)
{
Scene *it;
- BaseLegacy *base;
+ Base *base;
for (SETLOOPER(blenderscene, it, base)) {
base->object->lay = base->lay;
@@ -1911,7 +1911,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
Scene *blenderscene = kxscene->GetBlenderScene();
// for SETLOOPER
Scene *sce_iter;
- BaseLegacy *base;
+ Base *base;
// Get the frame settings of the canvas.
// Get the aspect ratio of the canvas as designed by the user.
diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
index dd93a6ff424..0c206dfce3d 100644
--- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
+++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
@@ -355,7 +355,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL
BLI_strncpy(bfd->main->name, progname, sizeof(bfd->main->name));
}
} else {
- bfd= BLO_read_from_file(progname, &reports);
+ bfd= BLO_read_from_file(progname, &reports, BLO_READ_SKIP_NONE);
}
if (!bfd && filename) {
diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp
index 89aea80bb67..4a97dc09f62 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -31,7 +31,7 @@
*/
-#include "glew-mx.h"
+#include "GPU_matrix.h"
#include "KX_Camera.h"
#include "KX_Scene.h"
#include "KX_PythonInit.h"
@@ -1048,19 +1048,21 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition,
}
const GLint *viewport;
- GLdouble win[3];
- GLdouble modelmatrix[16];
- GLdouble projmatrix[16];
+ GLfloat vec[3];
+ GLfloat win[3];
+ GLfloat modelmatrix[4][4];
+ GLfloat projmatrix[4][4];
MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
- m_modelmatrix.getValue(modelmatrix);
- m_projmatrix.getValue(projmatrix);
+ vect.getValue(vec);
+ m_modelmatrix.getValue((float*) modelmatrix);
+ m_projmatrix.getValue((float*) projmatrix);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
- gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
+ gpuProject(vec, modelmatrix, projmatrix, viewport, win);
vect[0] = (win[0] - viewport[0]) / viewport[2];
vect[1] = (win[1] - viewport[1]) / viewport[3];
@@ -1087,36 +1089,33 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect,
y = 1.0 - y; //to follow Blender window coordinate system (Top-Down)
- MT_Vector3 vect;
- MT_Point3 campos, screenpos;
-
const GLint *viewport;
- GLdouble win[3];
- GLdouble modelmatrix[16];
- GLdouble projmatrix[16];
+ GLfloat vec[3];
+ GLfloat win[3];
+ GLfloat modelmatrix[4][4];
+ GLfloat projmatrix[4][4];
MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera();
MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix();
- m_modelmatrix.getValue(modelmatrix);
- m_projmatrix.getValue(projmatrix);
+ m_modelmatrix.getValue((float*) modelmatrix);
+ m_projmatrix.getValue((float*) projmatrix);
viewport = KX_GetActiveEngine()->GetCanvas()->GetViewPort();
- vect[0] = x * viewport[2];
- vect[1] = y * viewport[3];
-
- vect[0] += viewport[0];
- vect[1] += viewport[1];
+ vec[0] = x * viewport[2];
+ vec[1] = y * viewport[3];
- vect[2] = 0.f;
+ vec[0] += viewport[0];
+ vec[1] += viewport[1];
- gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]);
+ vec[2] = 0.f;
- campos = this->GetCameraLocation();
- screenpos = MT_Point3(win[0], win[1], win[2]);
- vect = campos-screenpos;
+ gpuUnProject(vec, modelmatrix, projmatrix, viewport, win);
+ MT_Point3 campos = this->GetCameraLocation();
+ MT_Point3 screenpos(win[0], win[1], win[2]);
+ MT_Vector3 vect = campos - screenpos;
vect.normalize();
return PyObjectFrom(vect);
}
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index d08372e47d4..7abff85d39c 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -41,7 +41,7 @@
#include "RAS_CameraData.h"
#include "BLI_math.h"
-#include "glew-mx.h"
+#include "GPU_matrix.h"
// constructor
KX_Dome::KX_Dome (
@@ -1685,7 +1685,7 @@ void KX_Dome::DrawEnvMap(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
+ gpuLookAt(0.0f,0.0f,1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
glPolygonMode(GL_FRONT, GL_FILL);
glShadeModel(GL_SMOOTH);
@@ -1830,7 +1830,7 @@ void KX_Dome::DrawDomeFisheye(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
+ gpuLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
@@ -1913,7 +1913,7 @@ void KX_Dome::DrawPanorama(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
+ gpuLookAt(0.0f,-1.0f,0.0f, 0.0f,0.0f,0.0f, 0.0f,0.0f,1.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
@@ -1981,7 +1981,7 @@ void KX_Dome::DrawDomeWarped(void)
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- gluLookAt(0.0f, 0.0f, 1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
+ gpuLookAt(0.0f, 0.0f, 1.0f, 0.0f,0.0f,0.0f, 0.0f,1.0f,0.0f);
if (m_drawingmode == RAS_IRasterizer::KX_WIREFRAME)
glPolygonMode(GL_FRONT, GL_LINE);
diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
index fff988a07c5..d3bd7f74106 100644
--- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
+++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp
@@ -43,6 +43,7 @@
#include "DNA_lamp_types.h"
#include "DNA_scene_types.h"
+#include "GPU_lamp.h"
#include "GPU_material.h"
RAS_OpenGLLight::RAS_OpenGLLight(RAS_OpenGLRasterizer *ras)
diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp
index eed84a8580c..15a7e9e4cd1 100644
--- a/source/gameengine/VideoTexture/FilterColor.cpp
+++ b/source/gameengine/VideoTexture/FilterColor.cpp
@@ -68,7 +68,7 @@ PyTypeObject FilterGrayType =
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
- "Filter for gray scale effect", /* tp_doc */
+ "Filter for grayscale effect", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
diff --git a/source/gameengine/VideoTexture/FilterColor.h b/source/gameengine/VideoTexture/FilterColor.h
index 350f7270874..d042863d7e8 100644
--- a/source/gameengine/VideoTexture/FilterColor.h
+++ b/source/gameengine/VideoTexture/FilterColor.h
@@ -36,7 +36,7 @@
#include "FilterBase.h"
-/// pixel filter for gray scale
+/// pixel filter for grayscale
class FilterGray : public FilterBase
{
public:
@@ -53,7 +53,7 @@ protected:
// calculate gray value
unsigned int gray = (28 * (VT_B(val)) + 151 * (VT_G(val))
+ 77 * (VT_R(val))) >> 8;
- // return gray scale value
+ // return grayscale value
VT_R(val) = gray;
VT_G(val) = gray;
VT_B(val) = gray;
diff --git a/tests/gtests/blenlib/BLI_array_store_test.cc b/tests/gtests/blenlib/BLI_array_store_test.cc
index 5af6e639e64..370a4111bae 100644
--- a/tests/gtests/blenlib/BLI_array_store_test.cc
+++ b/tests/gtests/blenlib/BLI_array_store_test.cc
@@ -36,15 +36,15 @@ static void print_mem_saved(const char *id, const BArrayStore *bs)
/* -------------------------------------------------------------------- */
/* Test Chunks (building data from list of chunks) */
-typedef struct TestChunnk {
- struct TestChunnk *next, *prev;
+typedef struct TestChunk {
+ struct TestChunk *next, *prev;
const void *data;
size_t data_len;
-} TestChunnk;
+} TestChunk;
-static TestChunnk *testchunk_list_add(ListBase *lb, const void *data, size_t data_len)
+static TestChunk *testchunk_list_add(ListBase *lb, const void *data, size_t data_len)
{
- TestChunnk *tc = (TestChunnk *)MEM_mallocN(sizeof(*tc), __func__);
+ TestChunk *tc = (TestChunk *)MEM_mallocN(sizeof(*tc), __func__);
tc->data = data;
tc->data_len = data_len;
BLI_addtail(lb, tc);
@@ -53,7 +53,7 @@ static TestChunnk *testchunk_list_add(ListBase *lb, const void *data, size_t dat
}
#if 0
-static TestChunnk *testchunk_list_add_copydata(ListBase *lb, const void *data, size_t data_len)
+static TestChunk *testchunk_list_add_copydata(ListBase *lb, const void *data, size_t data_len)
{
void *data_copy = MEM_mallocN(data_len, __func__);
memcpy(data_copy, data, data_len);
@@ -63,7 +63,7 @@ static TestChunnk *testchunk_list_add_copydata(ListBase *lb, const void *data, s
static void testchunk_list_free(ListBase *lb)
{
- for (TestChunnk *tc = (TestChunnk *)lb->first, *tb_next; tc; tc = tb_next) {
+ for (TestChunk *tc = (TestChunk *)lb->first, *tb_next; tc; tc = tb_next) {
tb_next = tc->next;
MEM_freeN((void *)tc->data);
MEM_freeN(tc);
@@ -77,12 +77,12 @@ static char *testchunk_as_data(
size_t *r_data_len)
{
size_t data_len = 0;
- for (TestChunnk *tc = (TestChunnk *)lb->first; tc; tc = tc->next) {
+ for (TestChunk *tc = (TestChunk *)lb->first; tc; tc = tc->next) {
data_len += tc->data_len;
}
char *data = (char *)MEM_mallocN(data_len, __func__);
size_t i = 0;
- for (TestChunnk *tc = (TestChunnk *)lb->first; tc; tc = tc->next) {
+ for (TestChunk *tc = (TestChunk *)lb->first; tc; tc = tc->next) {
memcpy(&data[i], tc->data, tc->data_len);
data_len += tc->data_len;
i += tc->data_len;
@@ -95,7 +95,7 @@ static char *testchunk_as_data(
#endif
static char *testchunk_as_data_array(
- TestChunnk **tc_array, int tc_array_len,
+ TestChunk **tc_array, int tc_array_len,
size_t *r_data_len)
{
size_t data_len = 0;
@@ -105,7 +105,7 @@ static char *testchunk_as_data_array(
char *data = (char *)MEM_mallocN(data_len, __func__);
size_t i = 0;
for (int tc_index = 0; tc_index < tc_array_len; tc_index++) {
- TestChunnk *tc = tc_array[tc_index];
+ TestChunk *tc = tc_array[tc_index];
memcpy(&data[i], tc->data, tc->data_len);
i += tc->data_len;
}
@@ -677,9 +677,9 @@ static void random_chunk_mutate_helper(
ListBase random_chunks;
BLI_listbase_clear(&random_chunks);
random_chunk_generate(&random_chunks, chunks_per_buffer, stride, chunk_count, random_seed);
- TestChunnk **chunks_array = (TestChunnk **)MEM_mallocN(chunks_per_buffer * sizeof(TestChunnk *), __func__);
+ TestChunk **chunks_array = (TestChunk **)MEM_mallocN(chunks_per_buffer * sizeof(TestChunk *), __func__);
{
- TestChunnk *tc = (TestChunnk *)random_chunks.first;
+ TestChunk *tc = (TestChunk *)random_chunks.first;
for (int i = 0; i < chunks_per_buffer; i++, tc = tc->next) {
chunks_array[i] = tc;
}
@@ -692,7 +692,7 @@ static void random_chunk_mutate_helper(
{
RNG *rng = BLI_rng_new(random_seed);
for (int i = 0; i < items_total; i++) {
- BLI_rng_shuffle_array(rng, chunks_array, sizeof(TestChunnk *), chunks_per_buffer);
+ BLI_rng_shuffle_array(rng, chunks_array, sizeof(TestChunk *), chunks_per_buffer);
size_t data_len;
char *data = testchunk_as_data_array(chunks_array, chunks_per_buffer, &data_len);
BLI_assert(data_len == chunks_per_buffer * chunk_count * stride);
diff --git a/tests/gtests/blenlib/BLI_path_util_test.cc b/tests/gtests/blenlib/BLI_path_util_test.cc
index d017ab18b4d..ef469da50b2 100644
--- a/tests/gtests/blenlib/BLI_path_util_test.cc
+++ b/tests/gtests/blenlib/BLI_path_util_test.cc
@@ -5,6 +5,7 @@
extern "C" {
#include "BLI_fileops.h"
#include "BLI_path_util.h"
+#include "BLI_string.h"
#include "../../../source/blender/imbuf/IMB_imbuf.h"
#ifdef _WIN32
@@ -57,7 +58,7 @@ char *zLhm65070058860608_br_find_exe(const char *default_exe)
/* BLI_cleanup_path */
#ifndef _WIN32
-TEST(path_util, PathUtilClean)
+TEST(path_util, Clean)
{
/* "/./" -> "/" */
{
@@ -113,8 +114,238 @@ TEST(path_util, PathUtilClean)
}
#endif
+
+#define AT_INDEX(str_input, index_input, str_expect) \
+ { \
+ char path[] = str_input; \
+ const char *expect = str_expect; \
+ int index_output, len_output; \
+ const bool ret = BLI_path_name_at_index(path, index_input, &index_output, &len_output); \
+ if (expect == NULL) { \
+ EXPECT_EQ(ret, false); \
+ } \
+ else { \
+ EXPECT_EQ(ret, true); \
+ EXPECT_EQ(strlen(expect), len_output); \
+ path[index_output + len_output] = '\0'; \
+ EXPECT_STREQ(&path[index_output], expect); \
+ } \
+ }((void)0)
+
+/* BLI_path_name_at_index */
+TEST(path_util, NameAtIndex_Single)
+{
+ AT_INDEX("/a", 0, "a");
+ AT_INDEX("/a/", 0, "a");
+ AT_INDEX("a/", 0, "a");
+ AT_INDEX("//a//", 0, "a");
+ AT_INDEX("a/b", 0, "a");
+
+ AT_INDEX("/a", 1, NULL);
+ AT_INDEX("/a/", 1, NULL);
+ AT_INDEX("a/", 1, NULL);
+ AT_INDEX("//a//", 1, NULL);
+}
+TEST(path_util, NameAtIndex_SingleNeg)
+{
+ AT_INDEX("/a", -1, "a");
+ AT_INDEX("/a/", -1, "a");
+ AT_INDEX("a/", -1, "a");
+ AT_INDEX("//a//", -1, "a");
+ AT_INDEX("a/b", -1, "b");
+
+ AT_INDEX("/a", -2, NULL);
+ AT_INDEX("/a/", -2, NULL);
+ AT_INDEX("a/", -2, NULL);
+ AT_INDEX("//a//", -2, NULL);
+}
+
+TEST(path_util, NameAtIndex_Double)
+{
+ AT_INDEX("/ab", 0, "ab");
+ AT_INDEX("/ab/", 0, "ab");
+ AT_INDEX("ab/", 0, "ab");
+ AT_INDEX("//ab//", 0, "ab");
+ AT_INDEX("ab/c", 0, "ab");
+
+ AT_INDEX("/ab", 1, NULL);
+ AT_INDEX("/ab/", 1, NULL);
+ AT_INDEX("ab/", 1, NULL);
+ AT_INDEX("//ab//", 1, NULL);
+}
+
+TEST(path_util, NameAtIndex_DoublNeg)
+{
+ AT_INDEX("/ab", -1, "ab");
+ AT_INDEX("/ab/", -1, "ab");
+ AT_INDEX("ab/", -1, "ab");
+ AT_INDEX("//ab//", -1, "ab");
+ AT_INDEX("ab/c", -1, "c");
+
+ AT_INDEX("/ab", -2, NULL);
+ AT_INDEX("/ab/", -2, NULL);
+ AT_INDEX("ab/", -2, NULL);
+ AT_INDEX("//ab//", -2, NULL);
+}
+
+TEST(path_util, NameAtIndex_Misc)
+{
+ AT_INDEX("/how/now/brown/cow", 0, "how");
+ AT_INDEX("/how/now/brown/cow", 1, "now");
+ AT_INDEX("/how/now/brown/cow", 2, "brown");
+ AT_INDEX("/how/now/brown/cow", 3, "cow");
+ AT_INDEX("/how/now/brown/cow", 4, NULL);
+ AT_INDEX("/how/now/brown/cow/", 4, NULL);
+}
+
+TEST(path_util, NameAtIndex_MiscNeg)
+{
+ AT_INDEX("/how/now/brown/cow", 0, "how");
+ AT_INDEX("/how/now/brown/cow", 1, "now");
+ AT_INDEX("/how/now/brown/cow", 2, "brown");
+ AT_INDEX("/how/now/brown/cow", 3, "cow");
+ AT_INDEX("/how/now/brown/cow", 4, NULL);
+ AT_INDEX("/how/now/brown/cow/", 4, NULL);
+}
+
+TEST(path_util, NameAtIndex_MiscComplex)
+{
+ AT_INDEX("how//now/brown/cow", 0, "how");
+ AT_INDEX("//how///now\\/brown/cow", 1, "now");
+ AT_INDEX("/how/now\\//brown\\/cow", 2, "brown");
+ AT_INDEX("/how/now/brown/cow//\\", 3, "cow");
+ AT_INDEX("/how/now/brown/\\cow", 4, NULL);
+ AT_INDEX("how/now/brown/\\cow\\", 4, NULL);
+}
+
+TEST(path_util, NameAtIndex_MiscComplexNeg)
+{
+ AT_INDEX("how//now/brown/cow", -4, "how");
+ AT_INDEX("//how///now\\/brown/cow", -3, "now");
+ AT_INDEX("/how/now\\//brown\\/cow", -2, "brown");
+ AT_INDEX("/how/now/brown/cow//\\", -1, "cow");
+ AT_INDEX("/how/now/brown/\\cow", -5, NULL);
+ AT_INDEX("how/now/brown/\\cow\\", -5, NULL);
+}
+
+TEST(path_util, NameAtIndex_NoneComplex)
+{
+ AT_INDEX("", 0, NULL);
+ AT_INDEX("/", 0, NULL);
+ AT_INDEX("//", 0, NULL);
+ AT_INDEX("///", 0, NULL);
+}
+
+TEST(path_util, NameAtIndex_NoneComplexNeg)
+{
+ AT_INDEX("", -1, NULL);
+ AT_INDEX("/", -1, NULL);
+ AT_INDEX("//", -1, NULL);
+ AT_INDEX("///", -1, NULL);
+}
+
+#undef AT_INDEX
+
+#define JOIN(str_expect, out_size, ...) \
+ { \
+ const char *expect = str_expect; \
+ char result[(out_size) + 1024]; \
+ /* check we don't write past the last byte */ \
+ result[out_size] = '\0'; \
+ BLI_path_join(result, out_size, __VA_ARGS__, NULL); \
+ /* simplify expected string */ \
+ BLI_str_replace_char(result, '\\', '/'); \
+ EXPECT_STREQ(result, expect); \
+ EXPECT_EQ(result[out_size], '\0'); \
+ } ((void)0)
+
+/* BLI_path_join */
+TEST(path_util, JoinNop)
+{
+ JOIN("", 100, "");
+ JOIN("", 100, "", "");
+ JOIN("", 100, "", "", "");
+ JOIN("/", 100, "/", "", "");
+ JOIN("/", 100, "/", "/");
+ JOIN("/", 100, "/", "", "/");
+ JOIN("/", 100, "/", "", "/", "");
+}
+
+TEST(path_util, JoinSingle)
+{
+ JOIN("test", 100, "test");
+ JOIN("", 100, "");
+ JOIN("a", 100, "a");
+ JOIN("/a", 100, "/a");
+ JOIN("a/", 100, "a/");
+ JOIN("/a/", 100, "/a/");
+ JOIN("/a/", 100, "/a//");
+ JOIN("//a/", 100, "//a//");
+}
+
+TEST(path_util, JoinTriple)
+{
+ JOIN("/a/b/c", 100, "/a", "b", "c");
+ JOIN("/a/b/c", 100, "/a/", "/b/", "/c");
+ JOIN("/a/b/c", 100, "/a/b/", "/c");
+ JOIN("/a/b/c", 100, "/a/b/c");
+ JOIN("/a/b/c", 100, "/", "a/b/c");
+
+ JOIN("/a/b/c/", 100, "/a/", "/b/", "/c/");
+ JOIN("/a/b/c/", 100, "/a/b/c/");
+ JOIN("/a/b/c/", 100, "/a/b/", "/c/");
+ JOIN("/a/b/c/", 100, "/a/b/c", "/");
+ JOIN("/a/b/c/", 100, "/", "a/b/c", "/");
+}
+
+TEST(path_util, JoinTruncateShort)
+{
+ JOIN("", 1, "/");
+ JOIN("/", 2, "/");
+ JOIN("a", 2, "", "aa");
+ JOIN("a", 2, "", "a/");
+ JOIN("a/b", 4, "a", "bc");
+ JOIN("ab/", 4, "ab", "c");
+ JOIN("/a/", 4, "/a", "b");
+ JOIN("/a/", 4, "/a/", "b/");
+ JOIN("/a/", 4, "/a", "/b/");
+ JOIN("/a/", 4, "/", "a/b/");
+ JOIN("//a", 4, "//", "a/b/");
+
+ JOIN("/a/b", 5, "/a", "b", "c");
+}
+
+TEST(path_util, JoinTruncateLong)
+{
+ JOIN("", 1, "//", "//longer", "path");
+ JOIN("/", 2, "//", "//longer", "path");
+ JOIN("//", 3, "//", "//longer", "path");
+ JOIN("//l", 4, "//", "//longer", "path");
+ /* snip */
+ JOIN("//longe", 8, "//", "//longer", "path");
+ JOIN("//longer", 9, "//", "//longer", "path");
+ JOIN("//longer/", 10, "//", "//longer", "path");
+ JOIN("//longer/p", 11, "//", "//longer", "path");
+ JOIN("//longer/pa", 12, "//", "//longer", "path");
+ JOIN("//longer/pat", 13, "//", "//longer", "path");
+ JOIN("//longer/path", 14, "//", "//longer", "path"); // not truncated
+ JOIN("//longer/path", 14, "//", "//longer", "path/");
+ JOIN("//longer/path/", 15, "//", "//longer", "path/"); // not truncated
+ JOIN("//longer/path/", 15, "//", "//longer", "path/", "trunc");
+ JOIN("//longer/path/t", 16, "//", "//longer", "path/", "trunc");
+}
+
+TEST(path_util, JoinComplex)
+{
+ JOIN("/a/b/c/d/e/f/g/", 100, "/", "\\a/b", "//////c/d", "", "e\\\\", "f", "g//");
+ JOIN("/aa/bb/cc/dd/ee/ff/gg/", 100, "/", "\\aa/bb", "//////cc/dd", "", "ee\\\\", "ff", "gg//");
+ JOIN("1/2/3/", 100, "1", "////////", "", "2", "3\\");
+}
+
+#undef JOIN
+
/* BLI_path_frame */
-TEST(path_util, PathUtilFrame)
+TEST(path_util, Frame)
{
bool ret;
@@ -177,7 +408,7 @@ TEST(path_util, PathUtilFrame)
}
/* BLI_split_dirfile */
-TEST(path_util, PathUtilSplitDirfile)
+TEST(path_util, SplitDirfile)
{
{
const char *path = "";
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 4e0283adf88..5e02b05f995 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -83,11 +83,14 @@ add_test(script_pyapi_bpy_utils_units ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_bpy_utils_units.py
)
-# test running mathutils testing script
add_test(script_pyapi_mathutils ${TEST_BLENDER_EXE}
--python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_mathutils.py
)
+add_test(script_pyapi_idprop ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/bl_pyapi_idprop.py
+)
+
# ------------------------------------------------------------------------------
# MODELING TESTS
add_test(bevel ${TEST_BLENDER_EXE}
@@ -95,6 +98,11 @@ add_test(bevel ${TEST_BLENDER_EXE}
--python-text run_tests
)
+add_test(split_faces ${TEST_BLENDER_EXE}
+ ${TEST_SRC_DIR}/modeling/split_faces_test.blend
+ --python-text run_tests
+)
+
# ------------------------------------------------------------------------------
# IO TESTS
@@ -417,7 +425,12 @@ if(WITH_CYCLES)
-idiff "${OPENIMAGEIO_IDIFF}"
)
endif()
- endmacro()
+ endmacro()
+ if(WITH_OPENGL_TESTS)
+ add_cycles_render_test(opengl)
+ endif()
+ add_cycles_render_test(image)
+ add_cycles_render_test(mblur)
add_cycles_render_test(reports)
add_cycles_render_test(render)
add_cycles_render_test(shader)
@@ -426,9 +439,4 @@ if(WITH_CYCLES)
endif()
endif()
-# ------------------------------------------------------------------------------
-# LAYER SYSTEM TESTS
-add_test(render_layer ${TEST_BLENDER_EXE}
- --python ${CMAKE_CURRENT_LIST_DIR}/bl_render_layer.py --
- --testdir="${TEST_SRC_DIR}/layers"
-)
+add_subdirectory(render_layer)
diff --git a/tests/python/batch_import.py b/tests/python/batch_import.py
index 8fc679a7c15..bbe3a70327f 100644
--- a/tests/python/batch_import.py
+++ b/tests/python/batch_import.py
@@ -48,29 +48,17 @@ import os
import sys
-def clear_scene():
- import bpy
- unique_obs = set()
- for scene in bpy.data.scenes:
- for obj in scene.objects[:]:
- scene.objects.unlink(obj)
- unique_obs.add(obj)
-
- # remove obdata, for now only worry about the startup scene
- for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras):
- for id_data in bpy_data_iter:
- bpy_data_iter.remove(id_data)
-
-
-def batch_import(operator="",
- path="",
- save_path="",
- match="",
- start=0,
- end=sys.maxsize,
- ):
+def batch_import(
+ operator="",
+ path="",
+ save_path="",
+ match="",
+ start=0,
+ end=sys.maxsize,
+):
import addon_utils
_reset_all = addon_utils.reset_all # XXX, hack
+ _disable_all = addon_utils.disable_all # XXX, hack
import fnmatch
@@ -116,11 +104,12 @@ def batch_import(operator="",
# hack so loading the new file doesn't undo our loaded addons
addon_utils.reset_all = lambda: None # XXX, hack
+ addon_utils.disable_all = lambda: None # XXX, hack
- bpy.ops.wm.read_factory_settings()
+ bpy.ops.wm.read_factory_settings(use_empty=True)
addon_utils.reset_all = _reset_all # XXX, hack
- clear_scene()
+ addon_utils.disable_all = _disable_all # XXX, hack
result = op(filepath=f)
diff --git a/tests/python/bl_mesh_modifiers.py b/tests/python/bl_mesh_modifiers.py
index 526a54a49a2..bff2c31984c 100644
--- a/tests/python/bl_mesh_modifiers.py
+++ b/tests/python/bl_mesh_modifiers.py
@@ -31,7 +31,6 @@
import math
USE_QUICK_RENDER = False
-IS_BMESH = hasattr(__import__("bpy").types, "LoopColors")
# -----------------------------------------------------------------------------
# utility functions
@@ -203,13 +202,8 @@ def defaults_object(obj):
mesh.show_normal_vertex = True
- # lame!
- if IS_BMESH:
- for poly in mesh.polygons:
- poly.use_smooth = True
- else:
- for face in mesh.faces:
- face.use_smooth = True
+ for poly in mesh.polygons:
+ poly.use_smooth = True
def defaults_modifier(mod):
@@ -220,16 +214,14 @@ def defaults_modifier(mod):
# -----------------------------------------------------------------------------
# models (utils)
+def mesh_bmesh_poly_elems(poly, elems):
+ vert_start = poly.loop_start
+ vert_total = poly.loop_total
+ return elems[vert_start:vert_start + vert_total]
-if IS_BMESH:
- def mesh_bmesh_poly_elems(poly, elems):
- vert_start = poly.loop_start
- vert_total = poly.loop_total
- return elems[vert_start:vert_start + vert_total]
-
- def mesh_bmesh_poly_vertices(poly):
- return [loop.vertex_index
- for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)]
+def mesh_bmesh_poly_vertices(poly):
+ return [loop.vertex_index
+ for loop in mesh_bmesh_poly_elems(poly, poly.id_data.loops)]
def mesh_bounds(mesh):
@@ -258,21 +250,14 @@ def mesh_uv_add(obj):
uv_lay = obj.data.uv_textures.new()
- if IS_BMESH:
- # XXX, odd that we need to do this. until UV's and texface
- # are separated we will need to keep it
- uv_loops = obj.data.uv_layers[-1]
- uv_list = uv_loops.data[:]
- for poly in obj.data.polygons:
- poly_uvs = mesh_bmesh_poly_elems(poly, uv_list)
- for i, c in enumerate(poly_uvs):
- c.uv = uvs[i % 4]
- else:
- for uv in uv_lay.data:
- uv.uv1 = uvs[0]
- uv.uv2 = uvs[1]
- uv.uv3 = uvs[2]
- uv.uv4 = uvs[3]
+ # XXX, odd that we need to do this. until UV's and texface
+ # are separated we will need to keep it
+ uv_loops = obj.data.uv_layers[-1]
+ uv_list = uv_loops.data[:]
+ for poly in obj.data.polygons:
+ poly_uvs = mesh_bmesh_poly_elems(poly, uv_list)
+ for i, c in enumerate(poly_uvs):
+ c.uv = uvs[i % 4]
return uv_lay
@@ -296,21 +281,12 @@ def mesh_vcol_add(obj, mode=0):
mesh = obj.data
- if IS_BMESH:
- col_list = vcol_lay.data[:]
- for poly in mesh.polygons:
- face_verts = mesh_bmesh_poly_vertices(poly)
- poly_cols = mesh_bmesh_poly_elems(poly, col_list)
- for i, c in enumerate(poly_cols):
- c.color = colors_get(face_verts[i])
- else:
- for i, col in enumerate(vcol_lay.data):
- face_verts = mesh.faces[i].vertices
- col.color1 = colors_get(face_verts[0])
- col.color2 = colors_get(face_verts[1])
- col.color3 = colors_get(face_verts[2])
- if len(face_verts) == 4:
- col.color4 = colors_get(face_verts[3])
+ col_list = vcol_lay.data[:]
+ for poly in mesh.polygons:
+ face_verts = mesh_bmesh_poly_vertices(poly)
+ poly_cols = mesh_bmesh_poly_elems(poly, col_list)
+ for i, c in enumerate(poly_cols):
+ c.color = colors_get(face_verts[i])
return vcol_lay
@@ -470,10 +446,7 @@ def modifier_build_add(scene, obj):
defaults_modifier(mod)
# ensure we display some faces
- if IS_BMESH:
- totface = len(obj.data.polygons)
- else:
- totface = len(obj.data.faces)
+ totface = len(obj.data.polygons)
mod.frame_start = totface // 2
mod.frame_duration = totface
diff --git a/tests/python/bl_pyapi_idprop.py b/tests/python/bl_pyapi_idprop.py
new file mode 100644
index 00000000000..0a9cb044571
--- /dev/null
+++ b/tests/python/bl_pyapi_idprop.py
@@ -0,0 +1,144 @@
+# Apache License, Version 2.0
+
+# ./blender.bin --background -noaudio --python tests/python/bl_pyapi_idprop.py -- --verbose
+import bpy
+import unittest
+from array import array
+
+
+class TestHelper:
+
+ @property
+ def id(self):
+ return self._id
+
+ def setUp(self):
+ self._id = bpy.context.scene
+ assert(len(self._id.keys()) == 0)
+
+ def tearDown(self):
+ for key in list(self._id.keys()):
+ del self._id[key]
+
+ def assertAlmostEqualSeq(self, list1, list2):
+ self.assertEqual(len(list1), len(list2))
+ for v1, v2 in zip(list1, list2):
+ self.assertAlmostEqual(v1, v2, places=5)
+
+
+class TestIdPropertyCreation(TestHelper, unittest.TestCase):
+
+ def test_name_empty(self):
+ self.id[""] = 4
+ self.assertEqual(self.id[""], 4)
+
+ def test_name_too_long(self):
+ with self.assertRaises(KeyError):
+ self.id["name" * 30] = 4
+
+ def test_int(self):
+ self.id["a"] = 2
+ self.assertEqual(self.id["a"], 2)
+ self.assertTrue(isinstance(self.id["a"], int))
+
+ with self.assertRaises(OverflowError):
+ self.id["a"] = 2 ** 31 # integer <= 2 ** 31-1
+
+ def test_double(self):
+ self.id["a"] = 2.5
+ self.assertEqual(self.id["a"], 2.5)
+ self.assertTrue(isinstance(self.id["a"], float))
+
+ def test_unicode(self):
+ self.id["a"] = "Hello World"
+ self.assertEqual(self.id["a"], "Hello World")
+ self.assertTrue(isinstance(self.id["a"], str))
+
+ def test_bytes(self):
+ self.id["a"] = b"Hello World"
+ self.assertEqual(self.id["a"], b"Hello World")
+ self.assertTrue(isinstance(self.id["a"], bytes))
+
+ def test_sequence_double_list(self):
+ mylist = [1.2, 3.4, 5.6]
+ self.id["a"] = mylist
+ self.assertEqual(self.id["a"].to_list(), mylist)
+ self.assertEqual(self.id["a"].typecode, "d")
+
+ def test_sequence_int_list(self):
+ mylist = [1, 2, 3]
+ self.id["a"] = mylist
+ self.assertEqual(self.id["a"].to_list(), mylist)
+ self.assertEqual(self.id["a"].typecode, "i")
+
+ def test_sequence_float_array(self):
+ mylist = [1.2, 3.4, 5.6]
+ self.id["a"] = array("f", mylist)
+ self.assertAlmostEqualSeq(self.id["a"].to_list(), mylist)
+ self.assertEqual(self.id["a"].typecode, "d")
+
+ def test_sequence_double_array(self):
+ mylist = [1.2, 3.4, 5.6]
+ self.id["a"] = array("d", mylist)
+ self.assertAlmostEqualSeq(self.id["a"].to_list(), mylist)
+ self.assertEqual(self.id["a"].typecode, "d")
+
+ def test_sequence_int_array(self):
+ mylist = [1, 2, 3]
+ self.id["a"] = array("i", mylist)
+ self.assertAlmostEqualSeq(self.id["a"].to_list(), mylist)
+ self.assertEqual(self.id["a"].typecode, "i")
+
+ def test_sequence_other_array(self):
+ mylist = [1, 2, 3]
+ self.id["a"] = array("Q", mylist)
+ self.assertEqual(self.id["a"].to_list(), mylist)
+
+ def test_sequence_mixed_numerical_type(self):
+ self.id["a"] = [1, 2, 3.4, 5]
+ self.assertAlmostEqualSeq(self.id["a"].to_list(), [1.0, 2.0, 3.4, 5.0])
+ self.assertEqual(self.id["a"].typecode, "d")
+
+ def test_sequence_str_list(self):
+ # I'm a bit surprised that this works
+ mylist = ["abc", "qwe"]
+ self.id["a"] = mylist
+ self.assertEqual(self.id["a"], mylist)
+
+ def test_sequence_mixed_type(self):
+ with self.assertRaises(TypeError):
+ mylist = ["abc", 3, "qwe", 3.4]
+ self.id["a"] = mylist
+
+ def test_mapping_simple(self):
+ mydict = {"1": 10, "2": "20", "3": 30.5}
+ self.id["a"] = mydict
+ self.assertEqual(self.id["a"]["1"], mydict["1"])
+ self.assertEqual(self.id["a"]["2"], mydict["2"])
+ self.assertEqual(self.id["a"]["3"], mydict["3"])
+
+ def test_mapping_complex(self):
+ mydict = {
+ "1": [1, 2, 3],
+ "2": {"1": "abc", "2": array("i", [4, 5, 6])},
+ "3": {"1": {"1": 10}, "2": b"qwe"},
+ }
+ self.id["a"] = mydict
+ self.assertEqual(self.id["a"]["1"].to_list(), [1, 2, 3])
+ self.assertEqual(self.id["a"]["2"]["1"], "abc")
+ self.assertEqual(self.id["a"]["2"]["2"].to_list(), [4, 5, 6])
+ self.assertEqual(self.id["a"]["3"]["1"]["1"], 10)
+ self.assertEqual(self.id["a"]["3"]["2"], b"qwe")
+
+ with self.assertRaises(KeyError):
+ a = self.id["a"]["2"]["a"]
+
+ def test_invalid_type(self):
+ with self.assertRaises(TypeError):
+ self.id["a"] = self
+
+
+if __name__ == '__main__':
+ import sys
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [])
+ unittest.main()
diff --git a/tests/python/bl_render_layer.py b/tests/python/bl_render_layer.py
deleted file mode 100644
index e0b1711c9dc..00000000000
--- a/tests/python/bl_render_layer.py
+++ /dev/null
@@ -1,1040 +0,0 @@
-# Apache License, Version 2.0
-
-# ./blender.bin --background -noaudio --python tests/python/bl_render_layer.py -- --testdir="/data/lib/tests/"
-import unittest
-
-
-# ############################################################
-# Layer Collection Crawler
-# ############################################################
-
-def listbase_iter(data, struct, listbase):
- element = data.get_pointer((struct, listbase, b'first'))
- while element is not None:
- yield element
- element = element.get_pointer(b'next')
-
-
-def linkdata_iter(collection, data):
- element = collection.get_pointer((data, b'first'))
- while element is not None:
- yield element
- element = element.get_pointer(b'next')
-
-
-def get_layer_collection(layer_collection):
- data = {}
- flag = layer_collection.get(b'flag')
-
- data['is_visible'] = (flag & (1 << 0)) != 0;
- data['is_selectable'] = (flag & (1 << 1)) != 0;
- data['is_folded'] = (flag & (1 << 2)) != 0;
-
- scene_collection = layer_collection.get_pointer(b'scene_collection')
- if scene_collection is None:
- name = 'Fail!'
- else:
- name = scene_collection.get(b'name')
- data['name'] = name
-
- objects = []
- for link in linkdata_iter(layer_collection, b'object_bases'):
- ob_base = link.get_pointer(b'data')
- ob = ob_base.get_pointer(b'object')
- objects.append(ob.get((b'id', b'name'))[2:])
- data['objects'] = objects
-
- collections = {}
- for nested_layer_collection in linkdata_iter(layer_collection, b'layer_collections'):
- subname, subdata = get_layer_collection(nested_layer_collection)
- collections[subname] = subdata
- data['collections'] = collections
-
- return name, data
-
-
-def get_layer(layer):
- data = {}
- name = layer.get(b'name')
-
- data['name'] = name
- data['active_object'] = layer.get((b'basact', b'object', b'id', b'name'))[2:]
- data['engine'] = layer.get(b'engine')
-
- objects = []
- for link in linkdata_iter(layer, b'object_bases'):
- ob = link.get_pointer(b'object')
- objects.append(ob.get((b'id', b'name'))[2:])
- data['objects'] = objects
-
- collections = {}
- for layer_collection in linkdata_iter(layer, b'layer_collections'):
- subname, subdata = get_layer_collection(layer_collection)
- collections[subname] = subdata
- data['collections'] = collections
-
- return name, data
-
-
-def get_layers(scene):
- """Return all the render layers and their data"""
- layers = {}
- for layer in linkdata_iter(scene, b'render_layers'):
- name, data = get_layer(layer)
- layers[name] = data
- return layers
-
-
-def get_scene_collection_objects(collection, listbase):
- objects = []
- for link in linkdata_iter(collection, listbase):
- ob = link.get_pointer(b'data')
- if ob is None:
- name = 'Fail!'
- else:
- name = ob.get((b'id', b'name'))[2:]
- objects.append(name)
- return objects
-
-
-def get_scene_collection(collection):
- """"""
- data = {}
- name = collection.get(b'name')
-
- data['name'] = name
- data['filter'] = collection.get(b'filter')
-
- data['objects'] = get_scene_collection_objects(collection, b'objects')
- data['filter_objects'] = get_scene_collection_objects(collection, b'filter_objects')
-
- collections = {}
- for nested_collection in linkdata_iter(collection, b'scene_collections'):
- subname, subdata = get_scene_collection(nested_collection)
- collections[subname] = subdata
- data['collections'] = collections
-
- return name, data
-
-
-def get_scene_collections(scene):
- """Return all the scene collections ahd their data"""
- master_collection = scene.get_pointer(b'collection')
- return get_scene_collection(master_collection)
-
-
-def query_scene(filepath, name, callbacks):
- """Return the equivalent to bpy.context.scene"""
- import blendfile
- with blendfile.open_blend(filepath) as blend:
- scenes = [block for block in blend.blocks if block.code == b'SC']
- for scene in scenes:
- if scene.get((b'id', b'name'))[2:] == name:
- output = []
- for callback in callbacks:
- output.append(callback(scene))
- return output
-
-
-# ############################################################
-# Utils
-# ############################################################
-
-def import_blendfile():
- import bpy
- import os, sys
- path = os.path.join(
- bpy.utils.resource_path('LOCAL'),
- 'scripts',
- 'addons',
- 'io_blend_utils',
- 'blend',
- )
-
- if path not in sys.path:
- sys.path.append(path)
-
-
-def dump(data):
- import json
- return json.dumps(
- data,
- sort_keys=True,
- indent=4,
- separators=(',', ': '),
- )
-
-
-# ############################################################
-# Tests
-# ############################################################
-
-PDB = False
-DUMP_DIFF = True
-
-def compare_files(file_a, file_b):
- import filecmp
-
- if not filecmp.cmp(
- file_a,
- file_b):
-
- if DUMP_DIFF:
- import subprocess
- subprocess.call(["diff", "-u", file_a, file_b])
-
- if PDB:
- import pdb
- print("Files differ:", file_a, file_b)
- pdb.set_trace()
-
- return False
-
- return True
-
-
-class UnitsTesting(unittest.TestCase):
- _test_simple = False
-
- @classmethod
- def setUpClass(cls):
- """Runs once"""
- cls.pretest_import_blendfile()
- cls.pretest_parsing()
-
- @classmethod
- def setUp(cls):
- """Runs once per test"""
- import bpy
- bpy.ops.wm.read_factory_settings()
-
- def path_exists(self, filepath):
- import os
- self.assertTrue(
- os.path.exists(filepath),
- "Test file \"{0}\" not found".format(filepath))
-
- @classmethod
- def get_root(cls):
- """
- return the folder with the test files
- """
- arguments = {}
- for argument in extra_arguments:
- name, value = argument.split('=')
- cls.assertTrue(name and name.startswith("--"), "Invalid argument \"{0}\"".format(argument))
- cls.assertTrue(value, "Invalid argument \"{0}\"".format(argument))
- arguments[name[2:]] = value.strip('"')
-
- return arguments.get('testdir')
-
- @classmethod
- def pretest_parsing(cls):
- """
- Test if the arguments are properly set, and store ROOT
- name has extra _ because we need this test to run first
- """
- root = cls.get_root()
- cls.assertTrue(root, "Testdir not set")
-
- @staticmethod
- def pretest_import_blendfile():
- """
- Make sure blendfile imports with no problems
- name has extra _ because we need this test to run first
- """
- import_blendfile()
- import blendfile
-
- def do_scene_write_read(self, filepath_layers, filepath_layers_json, data_callbacks, do_read):
- """
- See if write/read is working for scene collections and layers
- """
- import bpy
- import os
- import tempfile
- import filecmp
-
- with tempfile.TemporaryDirectory() as dirpath:
- (self.path_exists(f) for f in (filepath_layers, filepath_layers_json))
-
- filepath_doversion = os.path.join(dirpath, 'doversion.blend')
- filepath_saved = os.path.join(dirpath, 'doversion_saved.blend')
- filepath_read_json = os.path.join(dirpath, "read.json")
-
- # doversion + write test
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
-
- datas = query_scene(filepath_doversion, 'Main', data_callbacks)
- self.assertTrue(datas, "Data is not valid")
-
- filepath_doversion_json = os.path.join(dirpath, "doversion.json")
- with open(filepath_doversion_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_doversion_json,
- filepath_layers_json,
- ),
- "Run: test_scene_write_layers")
-
- if do_read:
- # read test, simply open and save the file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
-
- datas = query_scene(filepath_saved, 'Main', data_callbacks)
- self.assertTrue(datas, "Data is not valid")
-
- with open(filepath_read_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_read_json,
- filepath_layers_json,
- ),
- "Scene dump files differ")
-
- def test_scene_write_collections(self):
- """
- See if the doversion and writing are working for scene collections
- """
- import os
-
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
-
- self.do_scene_write_read(
- filepath_layers,
- filepath_layers_json,
- (get_scene_collections,),
- False)
-
- def test_scene_write_layers(self):
- """
- See if the doversion and writing are working for collections and layers
- """
- import os
-
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_layers_json = os.path.join(ROOT, 'layers.json')
-
- self.do_scene_write_read(
- filepath_layers,
- filepath_layers_json,
- (get_scene_collections, get_layers),
- False)
-
- def test_scene_read_collections(self):
- """
- See if read is working for scene collections
- (run `test_scene_write_colections` first)
- """
- import os
-
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
-
- self.do_scene_write_read(
- filepath_layers,
- filepath_layers_json,
- (get_scene_collections,),
- True)
-
- def test_scene_read_layers(self):
- """
- See if read is working for scene layers
- (run `test_scene_write_layers` first)
- """
- import os
-
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_layers_json = os.path.join(ROOT, 'layers.json')
-
- self.do_scene_write_read(
- filepath_layers,
- filepath_layers_json,
- (get_scene_collections, get_layers),
- True)
-
- def do_scene_copy(self, filepath_json_reference, copy_mode, data_callbacks):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
-
- (self.path_exists(f) for f in (
- filepath_layers,
- filepath_json_reference,
- ))
-
- filepath_saved = os.path.join(dirpath, '{0}.blend'.format(copy_mode))
- filepath_json = os.path.join(dirpath, "{0}.json".format(copy_mode))
-
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
- bpy.ops.scene.new(type=copy_mode)
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
-
- datas = query_scene(filepath_saved, 'Main.001', data_callbacks)
- self.assertTrue(datas, "Data is not valid")
-
- with open(filepath_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_json,
- filepath_json_reference,
- ),
- "Scene copy \"{0}\" test failed".format(copy_mode.title()))
-
- def test_scene_collections_copy_full(self):
- """
- See if scene copying 'FULL_COPY' is working for scene collections
- """
- import os
- ROOT = self.get_root()
-
- filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full_simple.json')
- self.do_scene_copy(
- filepath_layers_json_copy,
- 'FULL_COPY',
- (get_scene_collections,))
-
- def test_scene_collections_link(self):
- """
- See if scene copying 'LINK_OBJECTS' is working for scene collections
- """
- import os
- ROOT = self.get_root()
-
- # note: nothing should change, so using `layers_simple.json`
- filepath_layers_json_copy = os.path.join(ROOT, 'layers_simple.json')
- self.do_scene_copy(
- filepath_layers_json_copy,
- 'LINK_OBJECTS',
- (get_scene_collections,))
-
- def test_scene_layers_copy(self):
- """
- See if scene copying 'FULL_COPY' is working for scene layers
- """
- import os
- ROOT = self.get_root()
-
- filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full.json')
- self.do_scene_copy(
- filepath_layers_json_copy,
- 'FULL_COPY',
- (get_scene_collections, get_layers))
-
- def test_scene_layers_link(self):
- """
- See if scene copying 'FULL_COPY' is working for scene layers
- """
- import os
- ROOT = self.get_root()
-
- filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_link.json')
- self.do_scene_copy(
- filepath_layers_json_copy,
- 'LINK_OBJECTS',
- (get_scene_collections, get_layers))
-
- def do_syncing(self, filepath_json, unlink_mode):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
- three_d = bpy.data.objects.get('T.3d')
-
- scene = bpy.context.scene
-
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = scene.master_collection.collections['1'].collections.new('scorpion')
-
- # test linking sync
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
-
- # test unlinking sync
- if unlink_mode in {'OBJECT', 'COLLECTION'}:
- scorpion.objects.link(three_d)
- scorpion.objects.unlink(three_d)
-
- if unlink_mode == 'COLLECTION':
- scorpion.objects.link(three_d)
- scene.master_collection.collections['1'].collections.remove(subzero)
- scene.master_collection.collections['1'].collections.remove(scorpion)
-
- # save file
- filepath_nested = os.path.join(dirpath, 'nested.blend')
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
-
- # get the generated json
- datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
- self.assertTrue(datas, "Data is not valid")
-
- filepath_nested_json = os.path.join(dirpath, "nested.json")
- with open(filepath_nested_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_nested_json,
- filepath_json,
- ),
- "Scene dump files differ")
-
- def test_syncing_link(self):
- """
- See if scene collections and layer collections are in sync
- when we create new subcollections and link new objects
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_nested.json')
- self.do_syncing(filepath_json, 'NONE')
-
- def test_syncing_unlink_object(self):
- """
- See if scene collections and layer collections are in sync
- when we create new subcollections, link new objects and unlink
- some.
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_nested.json')
- self.do_syncing(filepath_json, 'OBJECT')
-
- def test_syncing_unlink_collection(self):
- """
- See if scene collections and layer collections are in sync
- when we create new subcollections, link new objects and unlink full collections
- some.
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers.json')
- self.do_syncing(filepath_json, 'COLLECTION')
-
- def do_layer_linking(self, filepath_json, link_mode):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
-
- scene = bpy.context.scene
-
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
-
- # test linking sync
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
-
- # test unlinking sync
- layer = scene.render_layers.new('Fresh new Layer')
-
- if link_mode in {'COLLECTION_LINK', 'COLLECTION_UNLINK'}:
- layer.collections.link(subzero)
-
- if link_mode == 'COLLECTION_UNLINK':
- initial_collection = layer.collections['Master Collection']
- layer.collections.unlink(initial_collection)
-
- # save file
- filepath_nested = os.path.join(dirpath, 'nested.blend')
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
-
- # get the generated json
- datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
- self.assertTrue(datas, "Data is not valid")
-
- filepath_nested_json = os.path.join(dirpath, "nested.json")
- with open(filepath_nested_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_nested_json,
- filepath_json,
- ),
- "Scene dump files differ")
-
- def test_syncing_layer_new(self):
- """
- See if the creation of new layers is going well
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_new_layer.json')
- self.do_layer_linking(filepath_json, 'LAYER_NEW')
-
- def test_syncing_layer_collection_link(self):
- """
- See if the creation of new layers is going well
- And linking a new scene collection in the layer works
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_layer_collection_link.json')
- self.do_layer_linking(filepath_json, 'COLLECTION_LINK')
-
- def test_syncing_layer_collection_unlink(self):
- """
- See if the creation of new layers is going well
- And unlinking the origin scene collection works
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_layer_collection_unlink.json')
- self.do_layer_linking(filepath_json, 'COLLECTION_UNLINK')
-
- def test_active_collection(self):
- """
- See if active collection index is working
- layer.collections.active_index works recursively
- """
- import bpy
- import os
-
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
-
- scene = bpy.context.scene
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
- layer = scene.render_layers.new('Fresh new Layer')
- layer.collections.link(subzero)
-
- lookup = [
- 'Master Collection',
- '1',
- 'sub-zero',
- 'scorpion',
- '2',
- '3',
- '4',
- '5',
- 'sub-zero',
- 'scorpion']
-
- for i, name in enumerate(lookup):
- layer.collections.active_index = i
- self.assertEqual(name, layer.collections.active.name,
- "Collection index mismatch: [{0}] : {1} != {2}".format(
- i, name, layer.collections.active.name))
-
- def do_object_delete(self, del_mode):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_reference_json = os.path.join(ROOT, 'layers_object_delete.json')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_d = bpy.data.objects.get('T.3d')
-
- scene = bpy.context.scene
-
- # mangle the file a bit with some objects linked across collections
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
- subzero.objects.link(three_d)
- scorpion.objects.link(three_b)
- scorpion.objects.link(three_d)
-
- # object to delete
- ob = three_d
-
- # delete object
- if del_mode == 'DATA':
- bpy.data.objects.remove(ob, do_unlink=True)
-
- elif del_mode == 'OPERATOR':
- bpy.ops.object.select_all(action='DESELECT')
- ob.select_set(action='SELECT')
- bpy.ops.object.delete()
-
- # save file
- filepath_generated = os.path.join(dirpath, 'generated.blend')
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_generated)
-
- # get the generated json
- datas = query_scene(filepath_generated, 'Main', (get_scene_collections, get_layers))
- self.assertTrue(datas, "Data is not valid")
-
- filepath_generated_json = os.path.join(dirpath, "generated.json")
- with open(filepath_generated_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_generated_json,
- filepath_reference_json,
- ),
- "Scene dump files differ")
-
- def test_object_delete_data(self):
- """
- See if objects are removed correctly from all related collections
- bpy.data.objects.remove()
- """
- self.do_object_delete('DATA')
-
- def test_object_delete_operator(self):
- """
- See if new objects are added to the correct collection
- bpy.ops.object.del()
- """
- self.do_object_delete('OPERATOR')
-
- def do_link(self, master_collection):
- import bpy
- self.assertEqual(master_collection.name, "Master Collection")
- self.assertEqual(master_collection, bpy.context.scene.master_collection)
- master_collection.objects.link(bpy.data.objects.new('object', None))
-
- def test_link_scene(self):
- """
- See if we can link objects
- """
- import bpy
- master_collection = bpy.context.scene.master_collection
- self.do_link(master_collection)
-
- def test_link_context(self):
- """
- See if we can link objects via bpy.context.scene_collection
- """
- import bpy
- bpy.context.scene.render_layers.active_index = len(bpy.context.scene.render_layers) - 1
- master_collection = bpy.context.scene_collection
- self.do_link(master_collection)
-
- def test_operator_context(self):
- """
- See if render layer context is properly set/get with operators overrides
- when we set render_layer in context, the collection should change as well
- """
- import bpy
- import os
-
- class SampleOperator(bpy.types.Operator):
- bl_idname = "testing.sample"
- bl_label = "Sample Operator"
-
- render_layer = bpy.props.StringProperty(
- default="Not Set",
- options={'SKIP_SAVE'},
- )
-
- scene_collection = bpy.props.StringProperty(
- default="",
- options={'SKIP_SAVE'},
- )
-
- use_verbose = bpy.props.BoolProperty(
- default=False,
- options={'SKIP_SAVE'},
- )
-
- def execute(self, context):
- render_layer = context.render_layer
- ret = {'FINISHED'}
-
- # this is simply playing safe
- if render_layer.name != self.render_layer:
- if self.use_verbose:
- print('ERROR: Render Layer mismatch: "{0}" != "{1}"'.format(
- render_layer.name, self.render_layer))
- ret = {'CANCELLED'}
-
- scene_collection_name = None
- if self.scene_collection:
- scene_collection_name = self.scene_collection
- else:
- scene_collection_name = render_layer.collections.active.name
-
- # while this is the real test
- if context.scene_collection.name != scene_collection_name:
- if self.use_verbose:
- print('ERROR: Scene Collection mismatch: "{0}" != "{1}"'.format(
- context.scene_collection.name, scene_collection_name))
- ret = {'CANCELLED'}
- return ret
-
- bpy.utils.register_class(SampleOperator)
-
- # open sample file
- ROOT = self.get_root()
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # change the file
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
- scene = bpy.context.scene
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
- layer = scene.render_layers.new('Fresh new Layer')
- layer.collections.unlink(layer.collections.active)
- layer.collections.link(subzero)
- layer.collections.active_index = 3
- self.assertEqual(layer.collections.active.name, 'scorpion')
-
- scene = bpy.context.scene
- scene.render_layers.active_index = len(scene.render_layers) - 2
- self.assertEqual(scene.render_layers.active.name, "Render Layer")
-
- # old layer
- self.assertEqual(bpy.ops.testing.sample(render_layer='Render Layer', use_verbose=True), {'FINISHED'})
-
- # expected to fail
- self.assertTrue(bpy.ops.testing.sample(render_layer=layer.name), {'CANCELLED'})
-
- # set render layer and scene collection
- override = bpy.context.copy()
- override["render_layer"] = layer
- override["scene_collection"] = subzero
- self.assertEqual(bpy.ops.testing.sample(override,
- render_layer=layer.name,
- scene_collection=subzero.name, # 'sub-zero'
- use_verbose=True), {'FINISHED'})
-
- # set only render layer
- override = bpy.context.copy()
- override["render_layer"] = layer
-
- self.assertEqual(bpy.ops.testing.sample(override,
- render_layer=layer.name,
- scene_collection=layer.collections.active.name, # 'scorpion'
- use_verbose=True), {'FINISHED'})
-
- def do_object_add(self, filepath_json, add_mode):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
-
- scene = bpy.context.scene
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
- layer = scene.render_layers.new('Fresh new Layer')
- layer.collections.link(subzero)
-
- # change active collection
- layer.collections.active_index = 3
- self.assertEqual(layer.collections.active.name, 'scorpion', "Run: test_syncing_object_add")
-
- # change active layer
- override = bpy.context.copy()
- override["render_layer"] = layer
- override["scene_collection"] = layer.collections.active.collection
-
- # add new objects
- if add_mode == 'EMPTY':
- bpy.ops.object.add(override) # 'Empty'
-
- elif add_mode == 'CYLINDER':
- bpy.ops.mesh.primitive_cylinder_add(override) # 'Cylinder'
-
- elif add_mode == 'TORUS':
- bpy.ops.mesh.primitive_torus_add(override) # 'Torus'
-
- # save file
- filepath_objects = os.path.join(dirpath, 'objects.blend')
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
-
- # get the generated json
- datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
- self.assertTrue(datas, "Data is not valid")
-
- filepath_objects_json = os.path.join(dirpath, "objects.json")
- with open(filepath_objects_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_objects_json,
- filepath_json,
- ),
- "Scene dump files differ")
-
- def test_syncing_object_add_empty(self):
- """
- See if new objects are added to the correct collection
- bpy.ops.object.add()
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_object_add_empty.json')
- self.do_object_add(filepath_json, 'EMPTY')
-
- def test_syncing_object_add_cylinder(self):
- """
- See if new objects are added to the correct collection
- bpy.ops.mesh.primitive_cylinder_add()
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_object_add_cylinder.json')
- self.do_object_add(filepath_json, 'CYLINDER')
-
- def test_syncing_object_add_torus(self):
- """
- See if new objects are added to the correct collection
- bpy.ops.mesh.primitive_torus_add()
- """
- import os
- ROOT = self.get_root()
- filepath_json = os.path.join(ROOT, 'layers_object_add_torus.json')
- self.do_object_add(filepath_json, 'TORUS')
-
- def do_copy_object(self, mode):
- import bpy
- import os
- import tempfile
- import filecmp
-
- ROOT = self.get_root()
- with tempfile.TemporaryDirectory() as dirpath:
- filepath_layers = os.path.join(ROOT, 'layers.blend')
- filepath_json = os.path.join(ROOT, 'layers_object_copy_duplicate.json')
-
- # open file
- bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
-
- # create sub-collections
- three_b = bpy.data.objects.get('T.3b')
- three_c = bpy.data.objects.get('T.3c')
-
- scene = bpy.context.scene
- subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
- scorpion = subzero.collections.new('scorpion')
- subzero.objects.link(three_b)
- scorpion.objects.link(three_c)
- layer = scene.render_layers.new('Fresh new Layer')
- layer.collections.link(subzero)
-
- scene.render_layers.active_index = len(scene.render_layers) - 1
-
- if mode == 'DUPLICATE':
- # assuming the latest layer is the active layer
- bpy.ops.object.select_all(action='DESELECT')
- three_c.select_set(action='SELECT')
- bpy.ops.object.duplicate()
-
- elif mode == 'NAMED':
- bpy.ops.object.add_named(name=three_c.name)
-
- # save file
- filepath_objects = os.path.join(dirpath, 'objects.blend')
- bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
-
- # get the generated json
- datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
- self.assertTrue(datas, "Data is not valid")
-
- filepath_objects_json = os.path.join(dirpath, "objects.json")
- with open(filepath_objects_json, "w") as f:
- for data in datas:
- f.write(dump(data))
-
- self.assertTrue(compare_files(
- filepath_objects_json,
- filepath_json,
- ),
- "Scene dump files differ")
-
- def test_copy_object(self):
- """
- OBJECT_OT_duplicate
- """
- self.do_copy_object('DUPLICATE')
-
- def test_copy_object_named(self):
- """
- OBJECT_OT_add_named
- """
- self.do_copy_object('NAMED')
-
-
-# ############################################################
-# Main
-# ############################################################
-
-if __name__ == '__main__':
- import sys
-
- global extra_arguments
- extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
-
- sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
- unittest.main()
diff --git a/tests/python/bl_run_operators.py b/tests/python/bl_run_operators.py
index 7e92b424faa..7d5f4127378 100644
--- a/tests/python/bl_run_operators.py
+++ b/tests/python/bl_run_operators.py
@@ -65,6 +65,7 @@ op_blacklist = (
"wm.blenderplayer_start",
"wm.recover_auto_save",
"wm.quit_blender",
+ "wm.window_close",
"wm.url_open",
"wm.doc_view",
"wm.doc_edit",
@@ -308,16 +309,7 @@ def run_ops(operators, setup_func=None, reset=True):
# contexts
def ctx_clear_scene(): # copied from batch_import.py
- unique_obs = set()
- for scene in bpy.data.scenes:
- for obj in scene.objects[:]:
- scene.objects.unlink(obj)
- unique_obs.add(obj)
-
- # remove obdata, for now only worry about the startup scene
- for bpy_data_iter in (bpy.data.objects, bpy.data.meshes, bpy.data.lamps, bpy.data.cameras):
- for id_data in bpy_data_iter:
- bpy_data_iter.remove(id_data)
+ bpy.ops.wm.read_factory_settings(use_empty=True)
def ctx_editmode_mesh():
diff --git a/tests/python/cycles_render_tests.py b/tests/python/cycles_render_tests.py
index 64a71da301a..a030cc5e0de 100755
--- a/tests/python/cycles_render_tests.py
+++ b/tests/python/cycles_render_tests.py
@@ -47,20 +47,41 @@ def printMessage(type, status, message):
def render_file(filepath):
- command = (
- BLENDER,
- "--background",
- "-noaudio",
- "--factory-startup",
- "--enable-autoexec",
- filepath,
- "-E", "CYCLES",
- # Run with OSL enabled
- # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
- "-o", TEMP_FILE_MASK,
- "-F", "PNG",
- "-f", "1",
+ dirname = os.path.dirname(filepath)
+ basedir = os.path.dirname(dirname)
+ subject = os.path.basename(dirname)
+ if subject == 'opengl':
+ command = (
+ BLENDER,
+ "--window-geometry", "0", "0", "1", "1",
+ "-noaudio",
+ "--factory-startup",
+ "--enable-autoexec",
+ filepath,
+ "-E", "CYCLES",
+ # Run with OSL enabled
+ # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ '--python', os.path.join(basedir,
+ "util",
+ "render_opengl.py")
)
+ else:
+ command = (
+ BLENDER,
+ "--background",
+ "-noaudio",
+ "--factory-startup",
+ "--enable-autoexec",
+ filepath,
+ "-E", "CYCLES",
+ # Run with OSL enabled
+ # "--python-expr", "import bpy; bpy.context.scene.cycles.shading_system = True",
+ "-o", TEMP_FILE_MASK,
+ "-F", "PNG",
+ "-f", "1",
+ )
try:
output = subprocess.check_output(command)
if VERBOSE:
diff --git a/tests/python/render_layer/CMakeLists.txt b/tests/python/render_layer/CMakeLists.txt
new file mode 100644
index 00000000000..a6e159f2f96
--- /dev/null
+++ b/tests/python/render_layer/CMakeLists.txt
@@ -0,0 +1,159 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# Contributor(s): Jacques Beaurain, Dalai Felinto.
+#
+# ***** END GPL LICENSE BLOCK *****
+
+# --env-system-scripts allows to run without the install target.
+
+# Use '--write-blend=/tmp/test.blend' to view output
+
+set(TEST_SRC_DIR ${CMAKE_SOURCE_DIR}/../lib/tests)
+set(TEST_OUT_DIR ${CMAKE_BINARY_DIR}/tests)
+
+# ugh, any better way to do this on testing only?
+execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${TEST_OUT_DIR})
+
+#~ if(NOT IS_DIRECTORY ${TEST_SRC_DIR})
+#~ message(FATAL_ERROR "CMake test directory not found!")
+#~ endif()
+
+# all calls to blender use this
+if(APPLE)
+ if(${CMAKE_GENERATOR} MATCHES "Xcode")
+ set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/Debug/blender.app/Contents/MacOS/blender)
+ else()
+ set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/blender.app/Contents/MacOS/blender)
+ endif()
+else()
+ set(TEST_BLENDER_EXE ${EXECUTABLE_OUTPUT_PATH}/blender)
+endif()
+
+# for testing with valgrind prefix: valgrind --track-origins=yes --error-limit=no
+set(TEST_BLENDER_EXE ${TEST_BLENDER_EXE} --background -noaudio --factory-startup --env-system-scripts ${CMAKE_SOURCE_DIR}/release/scripts)
+
+
+# ------------------------------------------------------------------------------
+
+macro(RENDER_LAYER_TEST test_name)
+ add_test(render_layer_${test_name} ${TEST_BLENDER_EXE}
+ --python ${CMAKE_CURRENT_LIST_DIR}/test_${test_name}.py --
+ --testdir="${TEST_SRC_DIR}/layers"
+ )
+endmacro()
+
+RENDER_LAYER_TEST(active_collection)
+RENDER_LAYER_TEST(collection_rename)
+RENDER_LAYER_TEST(evaluation_visibility_a)
+RENDER_LAYER_TEST(evaluation_visibility_b)
+RENDER_LAYER_TEST(evaluation_visibility_c)
+RENDER_LAYER_TEST(evaluation_visibility_d)
+RENDER_LAYER_TEST(evaluation_visibility_e)
+RENDER_LAYER_TEST(evaluation_visibility_f)
+RENDER_LAYER_TEST(evaluation_visibility_g)
+RENDER_LAYER_TEST(evaluation_visibility_h)
+RENDER_LAYER_TEST(evaluation_visibility_i)
+RENDER_LAYER_TEST(evaluation_selectability_a)
+RENDER_LAYER_TEST(evaluation_selectability_b)
+RENDER_LAYER_TEST(evaluation_selectability_c)
+RENDER_LAYER_TEST(evaluation_selectability_d)
+RENDER_LAYER_TEST(evaluation_selectability_e)
+RENDER_LAYER_TEST(evaluation_selectability_f)
+RENDER_LAYER_TEST(object_add_cylinder)
+RENDER_LAYER_TEST(object_add_empty)
+RENDER_LAYER_TEST(object_add_torus)
+RENDER_LAYER_TEST(object_add_no_collection_cylinder)
+RENDER_LAYER_TEST(object_add_no_collection_empty)
+RENDER_LAYER_TEST(object_add_no_collection_torus)
+RENDER_LAYER_TEST(object_copy)
+RENDER_LAYER_TEST(object_delete_a)
+RENDER_LAYER_TEST(object_delete_b)
+RENDER_LAYER_TEST(object_link_a)
+RENDER_LAYER_TEST(object_link_b)
+RENDER_LAYER_TEST(object_link_c)
+RENDER_LAYER_TEST(operator_context)
+RENDER_LAYER_TEST(move_above_below_scene_collection_a)
+RENDER_LAYER_TEST(move_above_below_scene_collection_b)
+RENDER_LAYER_TEST(move_above_below_scene_collection_c)
+RENDER_LAYER_TEST(move_above_below_scene_collection_d)
+RENDER_LAYER_TEST(move_above_below_scene_collection_e)
+RENDER_LAYER_TEST(move_above_below_scene_collection_f)
+RENDER_LAYER_TEST(move_above_below_scene_collection_g)
+RENDER_LAYER_TEST(move_above_below_scene_collection_h)
+RENDER_LAYER_TEST(move_above_below_scene_collection_i)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_a)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_b)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_c)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_d)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_e)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_f)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_g)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_h)
+RENDER_LAYER_TEST(move_above_below_scene_collection_sync_i)
+RENDER_LAYER_TEST(move_into_scene_collection_a)
+RENDER_LAYER_TEST(move_into_scene_collection_b)
+RENDER_LAYER_TEST(move_into_scene_collection_c)
+RENDER_LAYER_TEST(move_into_scene_collection_d)
+RENDER_LAYER_TEST(move_into_scene_collection_e)
+RENDER_LAYER_TEST(move_into_scene_collection_f)
+RENDER_LAYER_TEST(move_into_scene_collection_g)
+RENDER_LAYER_TEST(move_into_scene_collection_h)
+RENDER_LAYER_TEST(move_into_scene_collection_i)
+RENDER_LAYER_TEST(move_into_scene_collection_j)
+RENDER_LAYER_TEST(move_into_scene_collection_k)
+RENDER_LAYER_TEST(move_into_scene_collection_l)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_a)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_b)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_c)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_d)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_e)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_f)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_g)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_h)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_i)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_j)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_k)
+RENDER_LAYER_TEST(move_into_scene_collection_sync_l)
+RENDER_LAYER_TEST(move_above_below_layer_collection_a)
+RENDER_LAYER_TEST(move_above_below_layer_collection_b)
+RENDER_LAYER_TEST(move_above_below_layer_collection_c)
+RENDER_LAYER_TEST(move_above_below_layer_collection_d)
+RENDER_LAYER_TEST(move_above_below_layer_collection_e)
+RENDER_LAYER_TEST(move_above_below_layer_collection_f)
+RENDER_LAYER_TEST(move_above_below_layer_collection_g)
+RENDER_LAYER_TEST(move_above_below_layer_collection_h)
+RENDER_LAYER_TEST(move_above_below_layer_collection_i)
+RENDER_LAYER_TEST(move_above_below_layer_collection_j)
+RENDER_LAYER_TEST(move_above_below_layer_collection_k)
+RENDER_LAYER_TEST(move_above_below_layer_collection_l)
+RENDER_LAYER_TEST(move_into_layer_collection_a)
+RENDER_LAYER_TEST(move_into_layer_collection_b)
+RENDER_LAYER_TEST(move_into_layer_collection_c)
+RENDER_LAYER_TEST(move_into_layer_collection_d)
+RENDER_LAYER_TEST(move_into_layer_collection_e)
+RENDER_LAYER_TEST(move_into_layer_collection_f)
+RENDER_LAYER_TEST(move_into_layer_collection_g)
+RENDER_LAYER_TEST(move_into_layer_collection_h)
+RENDER_LAYER_TEST(move_into_layer_collection_i)
+RENDER_LAYER_TEST(move_into_layer_collection_j)
+RENDER_LAYER_TEST(layer_linking)
+RENDER_LAYER_TEST(layer_syncinc)
+RENDER_LAYER_TEST(scene_copy_a)
+RENDER_LAYER_TEST(scene_copy_b)
+RENDER_LAYER_TEST(scene_copy_c)
+RENDER_LAYER_TEST(scene_copy_d)
+RENDER_LAYER_TEST(scene_write_read)
diff --git a/tests/python/render_layer/render_layer_common.py b/tests/python/render_layer/render_layer_common.py
new file mode 100644
index 00000000000..e1785dbd084
--- /dev/null
+++ b/tests/python/render_layer/render_layer_common.py
@@ -0,0 +1,721 @@
+import unittest
+
+# ############################################################
+# Layer Collection Crawler
+# ############################################################
+
+
+def listbase_iter(data, struct, listbase):
+ element = data.get_pointer((struct, listbase, b'first'))
+ while element is not None:
+ yield element
+ element = element.get_pointer(b'next')
+
+
+def linkdata_iter(collection, data):
+ element = collection.get_pointer((data, b'first'))
+ while element is not None:
+ yield element
+ element = element.get_pointer(b'next')
+
+
+def get_layer_collection(layer_collection):
+ data = {}
+ flag = layer_collection.get(b'flag')
+
+ data['is_visible'] = (flag & (1 << 0)) != 0
+ data['is_selectable'] = (flag & (1 << 1)) != 0
+ data['is_folded'] = True
+
+ scene_collection = layer_collection.get_pointer(b'scene_collection')
+ if scene_collection is None:
+ name = 'Fail!'
+ else:
+ name = scene_collection.get(b'name')
+ data['name'] = name
+
+ objects = []
+ for link in linkdata_iter(layer_collection, b'object_bases'):
+ ob_base = link.get_pointer(b'data')
+ ob = ob_base.get_pointer(b'object')
+ objects.append(ob.get((b'id', b'name'))[2:])
+ data['objects'] = objects
+
+ collections = {}
+ for nested_layer_collection in linkdata_iter(layer_collection, b'layer_collections'):
+ subname, subdata = get_layer_collection(nested_layer_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_layer(layer):
+ data = {}
+ name = layer.get(b'name')
+
+ data['name'] = name
+ data['active_object'] = layer.get((b'basact', b'object', b'id', b'name'))[2:]
+ data['engine'] = layer.get(b'engine')
+
+ objects = []
+ for link in linkdata_iter(layer, b'object_bases'):
+ ob = link.get_pointer(b'object')
+ objects.append(ob.get((b'id', b'name'))[2:])
+ data['objects'] = objects
+
+ collections = {}
+ for layer_collection in linkdata_iter(layer, b'layer_collections'):
+ subname, subdata = get_layer_collection(layer_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_layers(scene):
+ """Return all the render layers and their data"""
+ layers = {}
+ for layer in linkdata_iter(scene, b'render_layers'):
+ name, data = get_layer(layer)
+ layers[name] = data
+ return layers
+
+
+def get_scene_collection_objects(collection, listbase):
+ objects = []
+ for link in linkdata_iter(collection, listbase):
+ ob = link.get_pointer(b'data')
+ if ob is None:
+ name = 'Fail!'
+ else:
+ name = ob.get((b'id', b'name'))[2:]
+ objects.append(name)
+ return objects
+
+
+def get_scene_collection(collection):
+ """"""
+ data = {}
+ name = collection.get(b'name')
+
+ data['name'] = name
+ data['filter'] = collection.get(b'filter')
+
+ data['objects'] = get_scene_collection_objects(collection, b'objects')
+ data['filter_objects'] = get_scene_collection_objects(collection, b'filter_objects')
+
+ collections = {}
+ for nested_collection in linkdata_iter(collection, b'scene_collections'):
+ subname, subdata = get_scene_collection(nested_collection)
+ collections[subname] = subdata
+ data['collections'] = collections
+
+ return name, data
+
+
+def get_scene_collections(scene):
+ """Return all the scene collections ahd their data"""
+ master_collection = scene.get_pointer(b'collection')
+ return get_scene_collection(master_collection)
+
+
+def query_scene(filepath, name, callbacks):
+ """Return the equivalent to bpy.context.scene"""
+ import blendfile
+ with blendfile.open_blend(filepath) as blend:
+ scenes = [block for block in blend.blocks if block.code == b'SC']
+ for scene in scenes:
+ if scene.get((b'id', b'name'))[2:] == name:
+ output = []
+ for callback in callbacks:
+ output.append(callback(scene))
+ return output
+
+
+# ############################################################
+# Utils
+# ############################################################
+
+def import_blendfile():
+ import bpy
+ import os
+ import sys
+ path = os.path.join(
+ bpy.utils.resource_path('LOCAL'),
+ 'scripts',
+ 'addons',
+ 'io_blend_utils',
+ 'blend',
+ )
+
+ if path not in sys.path:
+ sys.path.append(path)
+
+
+def dump(data):
+ import json
+ return json.dumps(
+ data,
+ sort_keys=True,
+ indent=4,
+ separators=(',', ': '),
+ )
+
+
+# ############################################################
+# Tests
+# ############################################################
+
+PDB = False
+DUMP_DIFF = True
+
+
+def compare_files(file_a, file_b):
+ import filecmp
+
+ if not filecmp.cmp(
+ file_a,
+ file_b):
+
+ if DUMP_DIFF:
+ import subprocess
+ subprocess.call(["diff", "-u", file_a, file_b])
+
+ if PDB:
+ import pdb
+ print("Files differ:", file_a, file_b)
+ pdb.set_trace()
+
+ return False
+
+ return True
+
+
+class RenderLayerTesting(unittest.TestCase):
+ _test_simple = False
+ _extra_arguments = []
+
+ @classmethod
+ def setUpClass(cls):
+ """Runs once"""
+ cls.pretest_import_blendfile()
+ cls.pretest_parsing()
+
+ @classmethod
+ def get_root(cls):
+ """
+ return the folder with the test files
+ """
+ arguments = {}
+ for argument in cls._extra_arguments:
+ name, value = argument.split('=')
+ cls.assertTrue(name and name.startswith("--"), "Invalid argument \"{0}\"".format(argument))
+ cls.assertTrue(value, "Invalid argument \"{0}\"".format(argument))
+ arguments[name[2:]] = value.strip('"')
+
+ return arguments.get('testdir')
+
+ @classmethod
+ def pretest_parsing(cls):
+ """
+ Test if the arguments are properly set, and store ROOT
+ name has extra _ because we need this test to run first
+ """
+ root = cls.get_root()
+ cls.assertTrue(root, "Testdir not set")
+
+ @staticmethod
+ def pretest_import_blendfile():
+ """
+ Make sure blendfile imports with no problems
+ name has extra _ because we need this test to run first
+ """
+ import_blendfile()
+ import blendfile
+
+ def setUp(self):
+ """Runs once per test"""
+ import bpy
+ bpy.ops.wm.read_factory_settings()
+
+ def path_exists(self, filepath):
+ import os
+ self.assertTrue(
+ os.path.exists(filepath),
+ "Test file \"{0}\" not found".format(filepath))
+
+ def do_object_add(self, filepath_json, add_mode):
+ """
+ Testing for adding objects and see if they
+ go to the right collection
+ """
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ # change active collection
+ layer.collections.active_index = 3
+ self.assertEqual(layer.collections.active.name, 'scorpion', "Run: test_syncing_object_add")
+
+ # change active layer
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+ override["scene_collection"] = layer.collections.active.collection
+
+ # add new objects
+ if add_mode == 'EMPTY':
+ bpy.ops.object.add(override) # 'Empty'
+
+ elif add_mode == 'CYLINDER':
+ bpy.ops.mesh.primitive_cylinder_add(override) # 'Cylinder'
+
+ elif add_mode == 'TORUS':
+ bpy.ops.mesh.primitive_torus_add(override) # 'Torus'
+
+ # save file
+ filepath_objects = os.path.join(dirpath, 'objects.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
+
+ # get the generated json
+ datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_objects_json = os.path.join(dirpath, "objects.json")
+ with open(filepath_objects_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_objects_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def do_object_add_no_collection(self, add_mode):
+ """
+ Test for adding objects when no collection
+ exists in render layer
+ """
+ import bpy
+
+ # empty layer of collections
+
+ layer = bpy.context.render_layer
+ while layer.collections:
+ layer.collections.unlink(layer.collections[0])
+
+ # add new objects
+ if add_mode == 'EMPTY':
+ bpy.ops.object.add() # 'Empty'
+
+ elif add_mode == 'CYLINDER':
+ bpy.ops.mesh.primitive_cylinder_add() # 'Cylinder'
+
+ elif add_mode == 'TORUS':
+ bpy.ops.mesh.primitive_torus_add() # 'Torus'
+
+ self.assertEqual(len(layer.collections), 1, "New collection not created")
+ collection = layer.collections[0]
+ self.assertEqual(len(collection.objects), 1, "New collection is empty")
+
+ def do_object_link(self, master_collection):
+ import bpy
+ self.assertEqual(master_collection.name, "Master Collection")
+ self.assertEqual(master_collection, bpy.context.scene.master_collection)
+ master_collection.objects.link(bpy.data.objects.new('object', None))
+
+ def do_scene_copy(self, filepath_json_reference, copy_mode, data_callbacks):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ (self.path_exists(f) for f in (
+ filepath_layers,
+ filepath_json_reference,
+ ))
+
+ filepath_saved = os.path.join(dirpath, '{0}.blend'.format(copy_mode))
+ filepath_json = os.path.join(dirpath, "{0}.json".format(copy_mode))
+
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+ bpy.ops.scene.new(type=copy_mode)
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
+
+ datas = query_scene(filepath_saved, 'Main.001', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ with open(filepath_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_json,
+ filepath_json_reference,
+ ),
+ "Scene copy \"{0}\" test failed".format(copy_mode.title()))
+
+ def do_object_delete(self, del_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_reference_json = os.path.join(ROOT, 'layers_object_delete.json')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_d = bpy.data.objects.get('T.3d')
+
+ scene = bpy.context.scene
+
+ # mangle the file a bit with some objects linked across collections
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_d)
+ scorpion.objects.link(three_b)
+ scorpion.objects.link(three_d)
+
+ # object to delete
+ ob = three_d
+
+ # delete object
+ if del_mode == 'DATA':
+ bpy.data.objects.remove(ob, do_unlink=True)
+
+ elif del_mode == 'OPERATOR':
+ bpy.context.scene.update() # update depsgraph
+ bpy.ops.object.select_all(action='DESELECT')
+ ob.select_set(action='SELECT')
+ self.assertTrue(ob.select_get())
+ bpy.ops.object.delete()
+
+ # save file
+ filepath_generated = os.path.join(dirpath, 'generated.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_generated)
+
+ # get the generated json
+ datas = query_scene(filepath_generated, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_generated_json = os.path.join(dirpath, "generated.json")
+ with open(filepath_generated_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_generated_json,
+ filepath_reference_json,
+ ),
+ "Scene dump files differ")
+
+ def do_visibility_object_add(self, add_mode):
+ import bpy
+
+ scene = bpy.context.scene
+
+ # delete all objects of the file
+ for ob in bpy.data.objects:
+ bpy.data.objects.remove(ob, do_unlink=True)
+
+ # real test
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection = scene.master_collection.collections.new("Collection")
+ layer.collections.link(scene_collection)
+
+ bpy.context.scene.update() # update depsgraph
+
+ self.assertEqual(len(bpy.data.objects), 0)
+
+ # add new objects
+ if add_mode == 'EMPTY':
+ bpy.ops.object.add() # 'Empty'
+
+ elif add_mode == 'CYLINDER':
+ bpy.ops.mesh.primitive_cylinder_add() # 'Cylinder'
+
+ elif add_mode == 'TORUS':
+ bpy.ops.mesh.primitive_torus_add() # 'Torus'
+
+ self.assertEqual(len(bpy.data.objects), 1)
+
+ new_ob = bpy.data.objects[0]
+ self.assertTrue(new_ob.visible_get(), "Object should be visible")
+
+ def cleanup_tree(self):
+ """
+ Remove any existent layer and collections,
+ leaving only the one render_layer we can't remove
+ """
+ import bpy
+ scene = bpy.context.scene
+ while len(scene.render_layers) > 1:
+ scene.render_layers.remove(scene.render_layers[1])
+
+ layer = scene.render_layers[0]
+ while layer.collections:
+ layer.collections.unlink(layer.collections[0])
+
+ master_collection = scene.master_collection
+ while master_collection.collections:
+ master_collection.collections.remove(master_collection.collections[0])
+
+ def rename_collections(self, collection=None):
+ """
+ Rename 'Collection 1' to '1'
+ """
+ def strip_name(collection):
+ import re
+ if collection.name.startswith("Default Collection"):
+ collection.name = '1'
+ else:
+ collection.name = re.findall(r'\d+', collection.name)[0]
+
+ if collection is None:
+ import bpy
+ collection = bpy.context.scene.master_collection
+
+ for nested_collection in collection.collections:
+ strip_name(nested_collection)
+ self.rename_collections(nested_collection)
+
+
+class MoveSceneCollectionTesting(RenderLayerTesting):
+ """
+ To be used by tests of render_layer_move_into_scene_collection
+ """
+ def get_initial_scene_tree_map(self):
+ collections_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return collections_map
+
+ def build_scene_tree(self, tree_map, collection=None, ret_dict=None):
+ """
+ Returns a flat dictionary with new scene collections
+ created from a nested tuple of nested tuples (name, tuple)
+ """
+ import bpy
+
+ if collection is None:
+ collection = bpy.context.scene.master_collection
+
+ if ret_dict is None:
+ ret_dict = {collection.name: collection}
+ self.assertEqual(collection.name, "Master Collection")
+
+ for name, nested_collections in tree_map:
+ new_collection = collection.collections.new(name)
+ ret_dict[name] = new_collection
+
+ if nested_collections:
+ self.build_scene_tree(nested_collections, new_collection, ret_dict)
+
+ return ret_dict
+
+ def setup_tree(self):
+ """
+ Cleanup file, and populate it with class scene tree map
+ """
+ self.cleanup_tree()
+ self.assertTrue(
+ hasattr(self, "get_initial_scene_tree_map"),
+ "Test class has no get_initial_scene_tree_map method implemented")
+
+ return self.build_scene_tree(self.get_initial_scene_tree_map())
+
+ def get_scene_tree_map(self, collection=None, ret_list=None):
+ """
+ Extract the scene collection tree from scene
+ Return as a nested list of nested lists (name, list)
+ """
+ import bpy
+
+ if collection is None:
+ scene = bpy.context.scene
+ collection = scene.master_collection
+
+ if ret_list is None:
+ ret_list = []
+
+ for nested_collection in collection.collections:
+ new_collection = [nested_collection.name, None]
+ ret_list.append(new_collection)
+
+ if nested_collection.collections:
+ new_collection[1] = list()
+ self.get_scene_tree_map(nested_collection, new_collection[1])
+
+ return ret_list
+
+ def compare_tree_maps(self):
+ """
+ Compare scene with expected (class defined) data
+ """
+ self.assertEqual(self.get_scene_tree_map(), self.get_reference_scene_tree_map())
+
+
+class MoveSceneCollectionSyncTesting(MoveSceneCollectionTesting):
+ """
+ To be used by tests of render_layer_move_into_scene_collection_sync
+ """
+ def get_initial_layers_tree_map(self):
+ layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ 'C',
+ '3',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return layers_map
+
+ def get_reference_layers_tree_map(self):
+ """
+ For those classes we don't expect any changes in the layer tree
+ """
+ return self.get_initial_layers_tree_map()
+
+ def setup_tree(self):
+ tree = super(MoveSceneCollectionSyncTesting, self).setup_tree()
+
+ import bpy
+ scene = bpy.context.scene
+
+ self.assertTrue(
+ hasattr(self, "get_initial_layers_tree_map"),
+ "Test class has no get_initial_layers_tree_map method implemented")
+
+ layers_map = self.get_initial_layers_tree_map()
+
+ for layer_name, collections_names in layers_map:
+ layer = scene.render_layers.new(layer_name)
+ layer.collections.unlink(layer.collections[0])
+
+ for collection_name in collections_names:
+ layer.collections.link(tree[collection_name])
+
+ return tree
+
+ def compare_tree_maps(self):
+ """
+ Compare scene with expected (class defined) data
+ """
+ super(MoveSceneCollectionSyncTesting, self).compare_tree_maps()
+
+ import bpy
+ scene = bpy.context.scene
+ layers_map = self.get_reference_layers_tree_map()
+
+ for layer_name, collections_names in layers_map:
+ layer = scene.render_layers.get(layer_name)
+ self.assertTrue(layer)
+ self.assertEqual(len(collections_names), len(layer.collections))
+
+ for i, collection_name in enumerate(collections_names):
+ self.assertEqual(collection_name, layer.collections[i].name)
+ self.verify_collection_tree(layer.collections[i])
+
+ def verify_collection_tree(self, layer_collection):
+ """
+ Check if the LayerCollection mimics the SceneLayer tree
+ """
+ scene_collection = layer_collection.collection
+ self.assertEqual(len(layer_collection.collections), len(scene_collection.collections))
+
+ for i, nested_collection in enumerate(layer_collection.collections):
+ self.assertEqual(nested_collection.collection.name, scene_collection.collections[i].name)
+ self.assertEqual(nested_collection.collection, scene_collection.collections[i])
+ self.verify_collection_tree(nested_collection)
+
+
+class MoveLayerCollectionTesting(MoveSceneCollectionSyncTesting):
+ """
+ To be used by tests of render_layer_move_into_layer_collection
+ """
+ def parse_move(self, path, sep='.'):
+ """
+ convert 'Layer 1.C.2' into:
+ bpy.context.scene.render_layers['Layer 1'].collections['C'].collections['2']
+ """
+ import bpy
+
+ paths = path.split(sep)
+ layer = bpy.context.scene.render_layers[paths[0]]
+ collections = layer.collections
+
+ for subpath in paths[1:]:
+ collection = collections[subpath]
+ collections = collection.collections
+
+ return collection
+
+ def move_into(self, src, dst):
+ layer_collection_src = self.parse_move(src)
+ layer_collection_dst = self.parse_move(dst)
+ return layer_collection_src.move_into(layer_collection_dst)
+
+ def move_above(self, src, dst):
+ layer_collection_src = self.parse_move(src)
+ layer_collection_dst = self.parse_move(dst)
+ return layer_collection_src.move_above(layer_collection_dst)
+
+ def move_below(self, src, dst):
+ layer_collection_src = self.parse_move(src)
+ layer_collection_dst = self.parse_move(dst)
+ return layer_collection_src.move_below(layer_collection_dst)
diff --git a/tests/python/render_layer/test_active_collection.py b/tests/python/render_layer/test_active_collection.py
new file mode 100644
index 00000000000..37401046181
--- /dev/null
+++ b/tests/python/render_layer/test_active_collection.py
@@ -0,0 +1,76 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_active_collection(self):
+ """
+ See if active collection index is working
+ layer.collections.active_index works recursively
+ """
+ import bpy
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ lookup = [
+ 'Master Collection',
+ '1',
+ 'sub-zero',
+ 'scorpion',
+ '2',
+ '3',
+ '4',
+ '5',
+ 'sub-zero',
+ 'scorpion']
+
+ for i, name in enumerate(lookup):
+ layer.collections.active_index = i
+ self.assertEqual(
+ name, layer.collections.active.name,
+ "Collection index mismatch: [{0}] : {1} != {2}".format(
+ i, name, layer.collections.active.name))
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_collection_rename.py b/tests/python/render_layer/test_collection_rename.py
new file mode 100644
index 00000000000..f193c4bb3d6
--- /dev/null
+++ b/tests/python/render_layer/test_collection_rename.py
@@ -0,0 +1,82 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def setup_family(self):
+ import bpy
+ scene = bpy.context.scene
+
+ # Just add a bunch of collections on which we can do various tests.
+ grandma = scene.master_collection.collections.new('grandma')
+ grandpa = scene.master_collection.collections.new('grandpa')
+ mom = grandma.collections.new('mom')
+ son = mom.collections.new('son')
+ daughter = mom.collections.new('daughter')
+ uncle = grandma.collections.new('uncle')
+ cousin = uncle.collections.new('cousin')
+
+ lookup = {c.name: c for c in (grandma, grandpa, mom, son, daughter, uncle, cousin)}
+ return lookup
+
+ def test_rename_a(self):
+ family = self.setup_family()
+
+ family['mom'].name = family['daughter'].name
+ self.assertNotEqual(family['mom'].name, family['daughter'].name)
+
+ def test_rename_b(self):
+ family = self.setup_family()
+
+ family['grandma'].name = family['grandpa'].name
+ self.assertNotEqual(family['grandma'].name, family['grandpa'].name)
+
+ def test_rename_c(self):
+ family = self.setup_family()
+
+ family['cousin'].name = family['daughter'].name
+ self.assertNotEqual(family['cousin'].name, family['daughter'].name)
+
+ def test_rename_d(self):
+ family = self.setup_family()
+
+ family['son'].name = family['daughter'].name
+ self.assertNotEqual(family['son'].name, family['daughter'].name)
+
+ def test_add_equal_name_a(self):
+ family = self.setup_family()
+
+ other_daughter = family['mom'].collections.new(family['daughter'].name)
+ self.assertNotEqual(other_daughter.name, family['daughter'].name)
+
+ def test_add_equal_name_b(self):
+ family = self.setup_family()
+
+ other_aunt = family['grandma'].collections.new(family['daughter'].name)
+ self.assertNotEqual(other_aunt.name, family['daughter'].name)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_a.py b/tests/python/render_layer/test_evaluation_selectability_a.py
new file mode 100644
index 00000000000..10356cc2a5a
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_a.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Selectability Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = True
+ bpy.context.scene.update() # update depsgraph
+ cube.select_set('SELECT')
+
+ self.assertTrue(cube.visible_get(), "Cube should be visible")
+ self.assertTrue(cube.select_get(), "Cube should be selected")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_b.py b/tests/python/render_layer/test_evaluation_selectability_b.py
new file mode 100644
index 00000000000..2c33b5d17df
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_b.py
@@ -0,0 +1,60 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Selectability Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+ bpy.context.scene.update() # update depsgraph
+ cube.select_set('SELECT')
+
+ layer_collection_mom.collections[layer_collection_kid.name].hide = True
+ layer_collection_kid.hide = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertFalse(cube.visible_get(), "Cube should be invisible")
+ self.assertFalse(cube.select_get(), "Cube should be unselected")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_c.py b/tests/python/render_layer/test_evaluation_selectability_c.py
new file mode 100644
index 00000000000..848c525694f
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_c.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Selectability Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ bpy.context.scene.update() # update depsgraph
+ cube.select_set('SELECT')
+
+ self.assertTrue(cube.visible_get(), "Cube should be visible")
+ self.assertTrue(cube.select_get(), "Cube should be selected")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_d.py b/tests/python/render_layer/test_evaluation_selectability_d.py
new file mode 100644
index 00000000000..208be462703
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_d.py
@@ -0,0 +1,61 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Selectability Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ bpy.context.scene.update() # update depsgraph
+
+ cube.select_set('SELECT')
+ layer_collection_mom.collections[layer_collection_kid.name].hide_select = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Cube should be visible")
+ self.assertTrue(cube.select_get(), "Cube should be selected")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_e.py b/tests/python/render_layer/test_evaluation_selectability_e.py
new file mode 100644
index 00000000000..9920b917cd3
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_e.py
@@ -0,0 +1,60 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Selectability Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ cube.select_set('SELECT')
+ layer_collection_mom.collections[layer_collection_kid.name].hide_select = True
+ layer_collection_kid.hide = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Cube should be visible")
+ self.assertFalse(cube.select_get(), "Cube should be unselected")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_selectability_f.py b/tests/python/render_layer/test_evaluation_selectability_f.py
new file mode 100644
index 00000000000..436f2f5dfc7
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_selectability_f.py
@@ -0,0 +1,48 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_selectability(self):
+ import bpy
+ scene = bpy.context.scene
+
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+ scene_collection = scene.master_collection.collections.new('collection')
+ layer_collection = scene.render_layers.active.collections.link(scene_collection)
+
+ bpy.context.scene.update() # update depsgraph
+
+ scene_collection.objects.link(cube)
+
+ self.assertFalse(layer_collection.hide)
+ self.assertFalse(layer_collection.hide_select)
+
+ bpy.context.scene.update() # update depsgraph
+ cube.select_set(action='SELECT')
+ self.assertTrue(cube.select_get())
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_a.py b/tests/python/render_layer/test_evaluation_visibility_a.py
new file mode 100644
index 00000000000..db3d4693410
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_a.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene.master_collection.collections.new("Kid")
+
+ scene_collection_mom.objects.link(cube)
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = True
+ layer_collection_kid.hide = False
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Object should be visible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_b.py b/tests/python/render_layer/test_evaluation_visibility_b.py
new file mode 100644
index 00000000000..1d6c8582ccd
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_b.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ layer_collection_mom.collections[layer_collection_kid.name].hide = True
+ layer_collection_kid.hide = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertFalse(cube.visible_get(), "Object should be invisible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_c.py b/tests/python/render_layer/test_evaluation_visibility_c.py
new file mode 100644
index 00000000000..440b7444ff2
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_c.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ layer_collection_mom.collections[layer_collection_kid.name].hide = True
+ layer_collection_kid.hide = False
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Object should be visible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_d.py b/tests/python/render_layer/test_evaluation_visibility_d.py
new file mode 100644
index 00000000000..37c9f9d001d
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_d.py
@@ -0,0 +1,55 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Object should be visible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_e.py b/tests/python/render_layer/test_evaluation_visibility_e.py
new file mode 100644
index 00000000000..a6ec431e9a6
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_e.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_mom.objects.link(cube)
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ layer_collection_kid.hide = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Object should be visible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_f.py b/tests/python/render_layer/test_evaluation_visibility_f.py
new file mode 100644
index 00000000000..b04bceef5f5
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_f.py
@@ -0,0 +1,59 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ import bpy
+
+ scene = bpy.context.scene
+ cube = bpy.data.objects.new('guinea pig', bpy.data.meshes.new('mesh'))
+
+ layer = scene.render_layers.new('Visibility Test')
+ layer.collections.unlink(layer.collections[0])
+ scene.render_layers.active = layer
+
+ scene_collection_mom = scene.master_collection.collections.new("Mom")
+ scene_collection_kid = scene_collection_mom.collections.new("Kid")
+
+ scene_collection_mom.objects.link(cube)
+ scene_collection_kid.objects.link(cube)
+
+ layer_collection_mom = layer.collections.link(scene_collection_mom)
+ layer_collection_kid = layer.collections.link(scene_collection_kid)
+
+ layer_collection_mom.hide = False
+ layer_collection_mom.collections[layer_collection_kid.name].hide = True
+ layer_collection_kid.hide = True
+
+ bpy.context.scene.update() # update depsgraph
+ self.assertTrue(cube.visible_get(), "Object should be visible")
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_g.py b/tests/python/render_layer/test_evaluation_visibility_g.py
new file mode 100644
index 00000000000..434ec86707e
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_g.py
@@ -0,0 +1,36 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility_empty(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ self.do_visibility_object_add('EMPTY')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_h.py b/tests/python/render_layer/test_evaluation_visibility_h.py
new file mode 100644
index 00000000000..05b77e72842
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_h.py
@@ -0,0 +1,36 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility_cylinder(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ self.do_visibility_object_add('CYLINDER')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_evaluation_visibility_i.py b/tests/python/render_layer/test_evaluation_visibility_i.py
new file mode 100644
index 00000000000..5bc379e3a74
--- /dev/null
+++ b/tests/python/render_layer/test_evaluation_visibility_i.py
@@ -0,0 +1,36 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_visibility_torus(self):
+ """
+ See if the depsgraph evaluation is correct
+ """
+ self.do_visibility_object_add('TORUS')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_layer_linking.py b/tests/python/render_layer/test_layer_linking.py
new file mode 100644
index 00000000000..49b2a39edde
--- /dev/null
+++ b/tests/python/render_layer/test_layer_linking.py
@@ -0,0 +1,115 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def do_layer_linking(self, filepath_json, link_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+
+ # test linking sync
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+
+ # test unlinking sync
+ layer = scene.render_layers.new('Fresh new Layer')
+
+ if link_mode in {'COLLECTION_LINK', 'COLLECTION_UNLINK'}:
+ layer.collections.link(subzero)
+
+ if link_mode == 'COLLECTION_UNLINK':
+ initial_collection = layer.collections['Master Collection']
+ layer.collections.unlink(initial_collection)
+
+ # save file
+ filepath_nested = os.path.join(dirpath, 'nested.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
+
+ # get the generated json
+ datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_nested_json = os.path.join(dirpath, "nested.json")
+ with open(filepath_nested_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_nested_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_syncing_layer_new(self):
+ """
+ See if the creation of new layers is going well
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_new_layer.json')
+ self.do_layer_linking(filepath_json, 'LAYER_NEW')
+
+ def test_syncing_layer_collection_link(self):
+ """
+ See if the creation of new layers is going well
+ And linking a new scene collection in the layer works
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_layer_collection_link.json')
+ self.do_layer_linking(filepath_json, 'COLLECTION_LINK')
+
+ def test_syncing_layer_collection_unlink(self):
+ """
+ See if the creation of new layers is going well
+ And unlinking the origin scene collection works
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_layer_collection_unlink.json')
+ self.do_layer_linking(filepath_json, 'COLLECTION_UNLINK')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_a.py b/tests/python/render_layer/test_move_above_below_layer_collection_a.py
new file mode 100644
index 00000000000..b3671175263
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_a.py
@@ -0,0 +1,54 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 1.3', 'Layer 1.C'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_above('Layer 1.C', 'Layer 1.3'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_b.py b/tests/python/render_layer/test_move_above_below_layer_collection_b.py
new file mode 100644
index 00000000000..990936e86f1
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_b.py
@@ -0,0 +1,54 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 1.3.cat', 'Layer 1.3.dog'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_above('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_c.py b/tests/python/render_layer/test_move_above_below_layer_collection_c.py
new file mode 100644
index 00000000000..990936e86f1
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_c.py
@@ -0,0 +1,54 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 1.3.cat', 'Layer 1.3.dog'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_above('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_d.py b/tests/python/render_layer/test_move_above_below_layer_collection_d.py
new file mode 100644
index 00000000000..fab86e37388
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_d.py
@@ -0,0 +1,54 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_above('Layer 2.3.dog', 'Layer 1.C.2'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 1.C.2', 'Layer 2.3.dog'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_e.py b/tests/python/render_layer/test_move_above_below_layer_collection_e.py
new file mode 100644
index 00000000000..b6278e52fdd
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_e.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 1.Master Collection', 'Layer 1.C.1'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_f.py b/tests/python/render_layer/test_move_above_below_layer_collection_f.py
new file mode 100644
index 00000000000..a034b39abb6
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_f.py
@@ -0,0 +1,106 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def get_reference_layers_tree_map(self):
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ 'C',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_below('Layer 2.3', 'Layer 2.C.1'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_above('Layer 2.3', 'Layer 2.C.2'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 2.3')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # collection that will disappear
+ collection_old = self.parse_move('Layer 2.C.3')
+ collection_old.hide = True
+ collection_old.hide_select = False
+
+ # move
+ self.assertTrue(self.move_below('Layer 2.3', 'Layer 2.C.1'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 2.C.3')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_g.py b/tests/python/render_layer/test_move_above_below_layer_collection_g.py
new file mode 100644
index 00000000000..c3f44c55dda
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_g.py
@@ -0,0 +1,87 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['cat', None],
+ ['dog', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_above('Layer 2.C.3.cat', 'Layer 2.3.dog'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 2.C.3.cat')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # collection that will disappear
+ collection_old = self.parse_move('Layer 2.3.cat')
+ collection_old.hide = True
+ collection_old.hide_select = False
+
+ # move
+ self.assertTrue(self.move_above('Layer 2.C.3.cat', 'Layer 2.3.dog'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 2.3.cat')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_h.py b/tests/python/render_layer/test_move_above_below_layer_collection_h.py
new file mode 100644
index 00000000000..508c91c96df
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_h.py
@@ -0,0 +1,72 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_below('Layer 2.C.3.cat', 'Layer 2.3.dog'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 2.C.3.cat')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # collection that will disappear
+ collection_old = self.parse_move('Layer 2.3.cat')
+ collection_old.hide = True
+ collection_old.hide_select = False
+
+ # move
+ self.assertTrue(self.move_below('Layer 2.C.3.cat', 'Layer 2.3.dog'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 2.3.cat')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_i.py b/tests/python/render_layer/test_move_above_below_layer_collection_i.py
new file mode 100644
index 00000000000..a488086b670
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_i.py
@@ -0,0 +1,79 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ '3',
+ 'C',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_below('Layer 2.C', 'Layer 2.3'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 2.C')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # move
+ self.assertTrue(self.move_below('Layer 2.C', 'Layer 2.3'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 2.C')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_j.py b/tests/python/render_layer/test_move_above_below_layer_collection_j.py
new file mode 100644
index 00000000000..7810fbd2986
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_j.py
@@ -0,0 +1,69 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_below('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.assertTrue(self.move_above('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 1.3.dog')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # move
+ self.assertTrue(self.move_below('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.assertTrue(self.move_above('Layer 1.3.dog', 'Layer 1.3.cat'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 1.3.dog')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_k.py b/tests/python/render_layer/test_move_above_below_layer_collection_k.py
new file mode 100644
index 00000000000..74c28ce9e6c
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_k.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_move(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_below('Layer 2.C.2', 'Layer 2.3'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_layer_collection_l.py b/tests/python/render_layer/test_move_above_below_layer_collection_l.py
new file mode 100644
index 00000000000..6ab445ac6cd
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_layer_collection_l.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ 'C',
+ 'cat',
+ '3',
+ 'dog',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_below('Layer 2.cat', 'Layer 2.C'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_above('Layer 2.cat', 'Layer 2.3'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_a.py b/tests/python/render_layer/test_move_above_below_scene_collection_a.py
new file mode 100644
index 00000000000..794c27a2a31
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_a.py
@@ -0,0 +1,86 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_above(tree['dog']))
+ self.assertTrue(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['dog'].move_below(tree['cat']))
+ self.assertTrue(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['dog'].move_below(tree['cat']))
+ self.assertTrue(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_above(tree['dog']))
+ self.assertTrue(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_b.py b/tests/python/render_layer/test_move_above_below_scene_collection_b.py
new file mode 100644
index 00000000000..5216e60ed87
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_b.py
@@ -0,0 +1,75 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_above(tree['1']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['1'].move_below(tree['3']))
+ self.assertTrue(tree['2'].move_below(tree['1']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_above(tree['2']))
+ self.assertTrue(tree['1'].move_above(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_c.py b/tests/python/render_layer/test_move_above_below_scene_collection_c.py
new file mode 100644
index 00000000000..a4c98bd786b
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_c.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_below(tree['ii']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_d.py b/tests/python/render_layer/test_move_above_below_scene_collection_d.py
new file mode 100644
index 00000000000..cd4d9a7f27b
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_d.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['B', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_e.py b/tests/python/render_layer/test_move_above_below_scene_collection_e.py
new file mode 100644
index 00000000000..e2b89fcd98c
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_e.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['iii', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['iii'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['iii'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_f.py b/tests/python/render_layer/test_move_above_below_scene_collection_f.py
new file mode 100644
index 00000000000..87c5e3917be
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_f.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['A'].move_above(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_g.py b/tests/python/render_layer/test_move_above_below_scene_collection_g.py
new file mode 100644
index 00000000000..9124ef003f7
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_g.py
@@ -0,0 +1,50 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_h.py b/tests/python/render_layer/test_move_above_below_scene_collection_h.py
new file mode 100644
index 00000000000..79953ffce29
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_h.py
@@ -0,0 +1,90 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_above(collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_below(collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(collection.move_above(master_collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(collection.move_below(master_collection))
+
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_i.py b/tests/python/render_layer/test_move_above_below_scene_collection_i.py
new file mode 100644
index 00000000000..bc91e9b7ced
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_i.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_above(tree['2']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_below(tree['2']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_below(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_a.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_a.py
new file mode 100644
index 00000000000..75feb7dfada
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_a.py
@@ -0,0 +1,86 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_above(tree['dog']))
+ self.assertTrue(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['dog'].move_below(tree['cat']))
+ self.assertTrue(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['dog'].move_below(tree['cat']))
+ self.assertTrue(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_above(tree['dog']))
+ self.assertTrue(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_b.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_b.py
new file mode 100644
index 00000000000..b9fa33071f1
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_b.py
@@ -0,0 +1,75 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_above(tree['1']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['1'].move_below(tree['3']))
+ self.assertTrue(tree['2'].move_below(tree['1']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_above(tree['2']))
+ self.assertTrue(tree['1'].move_above(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_c.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_c.py
new file mode 100644
index 00000000000..95336513aaf
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_c.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_below(tree['ii']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_d.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_d.py
new file mode 100644
index 00000000000..fe89d34c472
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_d.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['B', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_e.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_e.py
new file mode 100644
index 00000000000..13197c4e9c4
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_e.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['iii', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['iii'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['iii'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_f.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_f.py
new file mode 100644
index 00000000000..33335089a07
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_f.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_move(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['A'].move_above(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_g.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_g.py
new file mode 100644
index 00000000000..304055ce330
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_g.py
@@ -0,0 +1,50 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['dog'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['cat'].move_below(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_h.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_h.py
new file mode 100644
index 00000000000..4079b05697c
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_h.py
@@ -0,0 +1,90 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_above(collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_below(collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(collection.move_above(master_collection))
+
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(collection.move_below(master_collection))
+
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_above_below_scene_collection_sync_i.py b/tests/python/render_layer/test_move_above_below_scene_collection_sync_i.py
new file mode 100644
index 00000000000..f3e20345ec0
--- /dev/null
+++ b/tests/python/render_layer/test_move_above_below_scene_collection_sync_i.py
@@ -0,0 +1,66 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_move_a(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_above(tree['2']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_b(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_below(tree['2']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_c(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_above(tree['cat']))
+ self.compare_tree_maps()
+
+ def test_scene_collection_move_d(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_below(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_a.py b/tests/python/render_layer/test_move_into_layer_collection_a.py
new file mode 100644
index 00000000000..ce2e7ca7741
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_a.py
@@ -0,0 +1,75 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ 'C',
+ '3',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into("Layer 1.C.2", "Layer 2.3"))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_b.py b/tests/python/render_layer/test_move_into_layer_collection_b.py
new file mode 100644
index 00000000000..d1d428f8cc3
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_b.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into('Layer 1.3', 'Layer 1.3.cat'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_c.py b/tests/python/render_layer/test_move_into_layer_collection_c.py
new file mode 100644
index 00000000000..5e6d09d813b
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_c.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into("Layer 2.C", "Layer 2.3"))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_d.py b/tests/python/render_layer/test_move_into_layer_collection_d.py
new file mode 100644
index 00000000000..1e5d2eca3ae
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_d.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into("Layer 2.3.cat", "Layer 2.3"))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_e.py b/tests/python/render_layer/test_move_into_layer_collection_e.py
new file mode 100644
index 00000000000..0c0a918ae3c
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_e.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into("Layer 1.Master Collection", "Layer 1.C"))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_f.py b/tests/python/render_layer/test_move_into_layer_collection_f.py
new file mode 100644
index 00000000000..f8cd992ad86
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_f.py
@@ -0,0 +1,92 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def get_reference_layers_tree_map(self):
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ ]],
+ ['Layer 2', [
+ 'C',
+ '3',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_into_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_into("Layer 1.3", "Layer 1.Master Collection.A"))
+ self.compare_tree_maps()
+
+ def test_layer_collection_into_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 1.3')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ self.assertTrue(self.move_into('Layer 1.3', 'Layer 1.Master Collection.A'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 1.Master Collection.A.3')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_g.py b/tests/python/render_layer/test_move_into_layer_collection_g.py
new file mode 100644
index 00000000000..754906ada4c
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_g.py
@@ -0,0 +1,83 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ reference_layers_map = [
+ ['Layer 1', [
+ 'Master Collection',
+ 'C',
+ '3',
+ ]],
+ ['Layer 2', [
+ 'C',
+ 'dog',
+ 'cat',
+ ]],
+ ]
+ return reference_layers_map
+
+ def test_layer_collection_into_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_into('Layer 2.3', 'Layer 2.C'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_into_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 2.3')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ # collection that will disappear
+ collection_old = self.parse_move('Layer 2.C.3')
+ collection_old.hide = True
+ collection_old.hide_select = False
+
+ # move collection
+ self.assertTrue(self.move_into('Layer 2.3', 'Layer 2.C'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 2.C.3')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_h.py b/tests/python/render_layer/test_move_into_layer_collection_h.py
new file mode 100644
index 00000000000..e353a15fd3e
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_h.py
@@ -0,0 +1,82 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', [
+ ['dog', None],
+ ]],
+ ['2', None],
+ ['3', [
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into_a(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertTrue(self.move_into('Layer 1.3.dog', 'Layer 1.C.1'))
+ self.compare_tree_maps()
+
+ def test_layer_collection_into_b(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+
+ # collection that will be moved
+ collection_original = self.parse_move('Layer 1.3.dog')
+ collection_original.hide = False
+ collection_original.hide_select = True
+
+ self.assertTrue(self.move_into('Layer 1.3.dog', 'Layer 1.C.1'))
+ self.compare_tree_maps()
+
+ # we expect the settings to be carried along from the
+ # original layer collection
+ collection_new = self.parse_move('Layer 1.C.1.dog')
+ self.assertEqual(collection_new.hide, False)
+ self.assertEqual(collection_new.hide_select, True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_i.py b/tests/python/render_layer/test_move_into_layer_collection_i.py
new file mode 100644
index 00000000000..b1d00247432
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_i.py
@@ -0,0 +1,46 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into('Layer 2.C.3', 'Layer 2.dog'))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_layer_collection_j.py b/tests/python/render_layer/test_move_into_layer_collection_j.py
new file mode 100644
index 00000000000..a86078ff769
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_layer_collection_j.py
@@ -0,0 +1,47 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveLayerCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def get_reference_layers_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_layers_tree_map()
+
+ def test_layer_collection_into(self):
+ """
+ Test outliner operations
+ Prevent collection from being dragged into itself
+ """
+ self.setup_tree()
+ self.assertFalse(self.move_into("Layer 2.dog", "Layer 2.3.dog"))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_a.py b/tests/python/render_layer/test_move_into_scene_collection_a.py
new file mode 100644
index 00000000000..7ffef8f9f99
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_a.py
@@ -0,0 +1,59 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_into(tree['2']))
+ self.assertTrue(tree['cat'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_b.py b/tests/python/render_layer/test_move_into_scene_collection_b.py
new file mode 100644
index 00000000000..099df22e1a7
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_b.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', [
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_into(tree['B']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_c.py b/tests/python/render_layer/test_move_into_scene_collection_c.py
new file mode 100644
index 00000000000..56162ebedcb
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_c.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['cat', None],
+ ]],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_d.py b/tests/python/render_layer/test_move_into_scene_collection_d.py
new file mode 100644
index 00000000000..8210627bf4a
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_d.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ # can't move into a collection if already the last item of the collection
+ self.assertFalse(tree['cat'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_e.py b/tests/python/render_layer/test_move_into_scene_collection_e.py
new file mode 100644
index 00000000000..12b9ec9b45b
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_e.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', [
+ ['B', None],
+ ]],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_into(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_f.py b/tests/python/render_layer/test_move_into_scene_collection_f.py
new file mode 100644
index 00000000000..4f8e0f601fc
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_f.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ['B', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_g.py b/tests/python/render_layer/test_move_into_scene_collection_g.py
new file mode 100644
index 00000000000..d9b6e16d913
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_g.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ]],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['A'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_h.py b/tests/python/render_layer/test_move_into_scene_collection_h.py
new file mode 100644
index 00000000000..ca3cb818535
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_h.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', [
+ ['ii', None],
+ ]],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['ii'].move_into(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_i.py b/tests/python/render_layer/test_move_into_scene_collection_i.py
new file mode 100644
index 00000000000..1ab49b86203
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_i.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['ii', None],
+ ]],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['ii'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_j.py b/tests/python/render_layer/test_move_into_scene_collection_j.py
new file mode 100644
index 00000000000..075cbff302b
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_j.py
@@ -0,0 +1,49 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_into(collection))
+
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_k.py b/tests/python/render_layer/test_move_into_scene_collection_k.py
new file mode 100644
index 00000000000..9bc8253cabf
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_k.py
@@ -0,0 +1,42 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_into(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_l.py b/tests/python/render_layer/test_move_into_scene_collection_l.py
new file mode 100644
index 00000000000..e063cd62c18
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_l.py
@@ -0,0 +1,42 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_into(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_a.py b/tests/python/render_layer/test_move_into_scene_collection_sync_a.py
new file mode 100644
index 00000000000..d5d0b7ea6a6
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_a.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_into(tree['2']))
+ self.assertTrue(tree['cat'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_b.py b/tests/python/render_layer/test_move_into_scene_collection_sync_b.py
new file mode 100644
index 00000000000..fb606e3b0d8
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_b.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', [
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['3'].move_into(tree['B']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_c.py b/tests/python/render_layer/test_move_into_scene_collection_sync_c.py
new file mode 100644
index 00000000000..bd927ec9463
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_c.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['cat', None],
+ ]],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['cat'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_d.py b/tests/python/render_layer/test_move_into_scene_collection_sync_d.py
new file mode 100644
index 00000000000..32ccd9d27c5
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_d.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ # can't move into a collection if already the last item of the collection
+ self.assertFalse(tree['cat'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_e.py b/tests/python/render_layer/test_move_into_scene_collection_sync_e.py
new file mode 100644
index 00000000000..70bc0341974
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_e.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', [
+ ['B', None],
+ ]],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_into(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_f.py b/tests/python/render_layer/test_move_into_scene_collection_sync_f.py
new file mode 100644
index 00000000000..6f7ad0eb4c7
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_f.py
@@ -0,0 +1,57 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ['B', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['B'].move_into(tree['3']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_g.py b/tests/python/render_layer/test_move_into_scene_collection_sync_g.py
new file mode 100644
index 00000000000..113f83e1c8b
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_g.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['A', [
+ ['i', None],
+ ['ii', None],
+ ['iii', None],
+ ]],
+ ]],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['A'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_h.py b/tests/python/render_layer/test_move_into_scene_collection_sync_h.py
new file mode 100644
index 00000000000..d70d681fb2b
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_h.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', [
+ ['ii', None],
+ ]],
+ ['3', [
+ ['dog', None],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['ii'].move_into(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_i.py b/tests/python/render_layer/test_move_into_scene_collection_sync_i.py
new file mode 100644
index 00000000000..a61830745e0
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_i.py
@@ -0,0 +1,58 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ reference_tree_map = [
+ ['A', [
+ ['i', None],
+ ['iii', None],
+ ]],
+ ['B', None],
+ ['C', [
+ ['1', None],
+ ['2', None],
+ ['3', [
+ ['dog', [
+ ['ii', None],
+ ]],
+ ['cat', None],
+ ]],
+ ]],
+ ]
+ return reference_tree_map
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertTrue(tree['ii'].move_into(tree['dog']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_j.py b/tests/python/render_layer/test_move_into_scene_collection_sync_j.py
new file mode 100644
index 00000000000..4075a0bc249
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_j.py
@@ -0,0 +1,49 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+
+ tree = self.setup_tree()
+
+ for collection in tree.values():
+ # can't move into master_collection anywhere
+ self.assertFalse(master_collection.move_into(collection))
+
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_k.py b/tests/python/render_layer/test_move_into_scene_collection_sync_k.py
new file mode 100644
index 00000000000..12aa70c65b3
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_k.py
@@ -0,0 +1,42 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_into(tree['2']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_move_into_scene_collection_sync_l.py b/tests/python/render_layer/test_move_into_scene_collection_sync_l.py
new file mode 100644
index 00000000000..195fa4cfcc4
--- /dev/null
+++ b/tests/python/render_layer/test_move_into_scene_collection_sync_l.py
@@ -0,0 +1,42 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(MoveSceneCollectionSyncTesting):
+ def get_reference_scene_tree_map(self):
+ # original tree, no changes
+ return self.get_initial_scene_tree_map()
+
+ def test_scene_collection_into(self):
+ """
+ Test outliner operations
+ """
+ tree = self.setup_tree()
+ self.assertFalse(tree['C'].move_into(tree['cat']))
+ self.compare_tree_maps()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_cylinder.py b/tests/python/render_layer/test_object_add_cylinder.py
new file mode 100644
index 00000000000..8dfb84ac488
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_cylinder.py
@@ -0,0 +1,40 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_syncing_object_add_cylinder(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_cylinder_add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_cylinder.json')
+ self.do_object_add(filepath_json, 'CYLINDER')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_empty.py b/tests/python/render_layer/test_object_add_empty.py
new file mode 100644
index 00000000000..896181a2c42
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_empty.py
@@ -0,0 +1,40 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_syncing_object_add_empty(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.object.add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_empty.json')
+ self.do_object_add(filepath_json, 'EMPTY')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_no_collection_cylinder.py b/tests/python/render_layer/test_object_add_no_collection_cylinder.py
new file mode 100644
index 00000000000..a77c65853de
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_no_collection_cylinder.py
@@ -0,0 +1,38 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_add_cylinder(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_cylinder_add()
+ """
+ import os
+ self.do_object_add_no_collection('CYLINDER')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_no_collection_empty.py b/tests/python/render_layer/test_object_add_no_collection_empty.py
new file mode 100644
index 00000000000..b5af5aa54f7
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_no_collection_empty.py
@@ -0,0 +1,37 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_syncing_object_add_empty(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.object.add()
+ """
+ self.do_object_add_no_collection('EMPTY')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_no_collection_torus.py b/tests/python/render_layer/test_object_add_no_collection_torus.py
new file mode 100644
index 00000000000..dd08ef0ce02
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_no_collection_torus.py
@@ -0,0 +1,37 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_syncing_object_add_torus(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_torus_add()
+ """
+ self.do_object_add_no_collection('TORUS')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_add_torus.py b/tests/python/render_layer/test_object_add_torus.py
new file mode 100644
index 00000000000..3de14397951
--- /dev/null
+++ b/tests/python/render_layer/test_object_add_torus.py
@@ -0,0 +1,40 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_syncing_object_add_torus(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.mesh.primitive_torus_add()
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_object_add_torus.json')
+ self.do_object_add(filepath_json, 'TORUS')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_copy.py b/tests/python/render_layer/test_object_copy.py
new file mode 100644
index 00000000000..5de777985e4
--- /dev/null
+++ b/tests/python/render_layer/test_object_copy.py
@@ -0,0 +1,99 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def do_object_copy(self, mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_json = os.path.join(ROOT, 'layers_object_copy_duplicate.json')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.link(subzero)
+
+ scene.render_layers.active_index = len(scene.render_layers) - 1
+
+ if mode == 'DUPLICATE':
+ # assuming the latest layer is the active layer
+ bpy.ops.object.select_all(action='DESELECT')
+ three_c.select_set(action='SELECT')
+ bpy.ops.object.duplicate()
+
+ elif mode == 'NAMED':
+ bpy.ops.object.add_named(name=three_c.name)
+
+ # save file
+ filepath_objects = os.path.join(dirpath, 'objects.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_objects)
+
+ # get the generated json
+ datas = query_scene(filepath_objects, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_objects_json = os.path.join(dirpath, "objects.json")
+ with open(filepath_objects_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_objects_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_copy_object(self):
+ """
+ OBJECT_OT_duplicate
+ """
+ self.do_object_copy('DUPLICATE')
+
+ def test_copy_object_named(self):
+ """
+ OBJECT_OT_add_named
+ """
+ self.do_object_copy('NAMED')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_delete_a.py b/tests/python/render_layer/test_object_delete_a.py
new file mode 100644
index 00000000000..4a72ca06f46
--- /dev/null
+++ b/tests/python/render_layer/test_object_delete_a.py
@@ -0,0 +1,37 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_delete_data(self):
+ """
+ See if objects are removed correctly from all related collections
+ bpy.data.objects.remove()
+ """
+ self.do_object_delete('DATA')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_delete_b.py b/tests/python/render_layer/test_object_delete_b.py
new file mode 100644
index 00000000000..f6451c4256c
--- /dev/null
+++ b/tests/python/render_layer/test_object_delete_b.py
@@ -0,0 +1,37 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_delete_operator(self):
+ """
+ See if new objects are added to the correct collection
+ bpy.ops.object.del()
+ """
+ self.do_object_delete('OPERATOR')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_link_a.py b/tests/python/render_layer/test_object_link_a.py
new file mode 100644
index 00000000000..0058e7908d0
--- /dev/null
+++ b/tests/python/render_layer/test_object_link_a.py
@@ -0,0 +1,38 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_link_scene(self):
+ """
+ See if we can link objects
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+ self.do_object_link(master_collection)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_link_b.py b/tests/python/render_layer/test_object_link_b.py
new file mode 100644
index 00000000000..ecd8c4ff29f
--- /dev/null
+++ b/tests/python/render_layer/test_object_link_b.py
@@ -0,0 +1,39 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_link_context(self):
+ """
+ See if we can link objects via bpy.context.scene_collection
+ """
+ import bpy
+ bpy.context.scene.render_layers.active_index = len(bpy.context.scene.render_layers) - 1
+ master_collection = bpy.context.scene_collection
+ self.do_object_link(master_collection)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_object_link_c.py b/tests/python/render_layer/test_object_link_c.py
new file mode 100644
index 00000000000..02eb13b0c92
--- /dev/null
+++ b/tests/python/render_layer/test_object_link_c.py
@@ -0,0 +1,41 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_object_link_reload(self):
+ """
+ See if we can link objects and not crash
+ """
+ import bpy
+ master_collection = bpy.context.scene.master_collection
+ self.do_object_link(master_collection)
+
+ # force depsgraph to update
+ bpy.ops.wm.read_factory_settings()
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_operator_context.py b/tests/python/render_layer/test_operator_context.py
new file mode 100644
index 00000000000..77c8a1999f2
--- /dev/null
+++ b/tests/python/render_layer/test_operator_context.py
@@ -0,0 +1,134 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_operator_context(self):
+ """
+ See if render layer context is properly set/get with operators overrides
+ when we set render_layer in context, the collection should change as well
+ """
+ import bpy
+ import os
+
+ class SampleOperator(bpy.types.Operator):
+ bl_idname = "testing.sample"
+ bl_label = "Sample Operator"
+
+ render_layer = bpy.props.StringProperty(
+ default="Not Set",
+ options={'SKIP_SAVE'},
+ )
+
+ scene_collection = bpy.props.StringProperty(
+ default="",
+ options={'SKIP_SAVE'},
+ )
+
+ use_verbose = bpy.props.BoolProperty(
+ default=False,
+ options={'SKIP_SAVE'},
+ )
+
+ def execute(self, context):
+ render_layer = context.render_layer
+ ret = {'FINISHED'}
+
+ # this is simply playing safe
+ if render_layer.name != self.render_layer:
+ if self.use_verbose:
+ print('ERROR: Render Layer mismatch: "{0}" != "{1}"'.format(
+ render_layer.name, self.render_layer))
+ ret = {'CANCELLED'}
+
+ scene_collection_name = None
+ if self.scene_collection:
+ scene_collection_name = self.scene_collection
+ else:
+ scene_collection_name = render_layer.collections.active.name
+
+ # while this is the real test
+ if context.scene_collection.name != scene_collection_name:
+ if self.use_verbose:
+ print('ERROR: Scene Collection mismatch: "{0}" != "{1}"'.format(
+ context.scene_collection.name, scene_collection_name))
+ ret = {'CANCELLED'}
+ return ret
+
+ bpy.utils.register_class(SampleOperator)
+
+ # open sample file
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # change the file
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+ scene = bpy.context.scene
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = subzero.collections.new('scorpion')
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+ layer = scene.render_layers.new('Fresh new Layer')
+ layer.collections.unlink(layer.collections.active)
+ layer.collections.link(subzero)
+ layer.collections.active_index = 3
+ self.assertEqual(layer.collections.active.name, 'scorpion')
+
+ scene = bpy.context.scene
+ scene.render_layers.active_index = len(scene.render_layers) - 2
+ self.assertEqual(scene.render_layers.active.name, "Viewport")
+
+ # old layer
+ self.assertEqual(bpy.ops.testing.sample(render_layer='Viewport', use_verbose=True), {'FINISHED'})
+
+ # expected to fail
+ self.assertTrue(bpy.ops.testing.sample(render_layer=layer.name), {'CANCELLED'})
+
+ # set render layer and scene collection
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+ override["scene_collection"] = subzero
+ self.assertEqual(bpy.ops.testing.sample(
+ override,
+ render_layer=layer.name,
+ scene_collection=subzero.name, # 'sub-zero'
+ use_verbose=True), {'FINISHED'})
+
+ # set only render layer
+ override = bpy.context.copy()
+ override["render_layer"] = layer
+
+ self.assertEqual(bpy.ops.testing.sample(
+ override,
+ render_layer=layer.name,
+ scene_collection=layer.collections.active.name, # 'scorpion'
+ use_verbose=True), {'FINISHED'})
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_scene_copy_a.py b/tests/python/render_layer/test_scene_copy_a.py
new file mode 100644
index 00000000000..b8973e9c4b3
--- /dev/null
+++ b/tests/python/render_layer/test_scene_copy_a.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_scene_collections_copy_full(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene collections
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full_simple.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'FULL_COPY',
+ (get_scene_collections,))
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_scene_copy_b.py b/tests/python/render_layer/test_scene_copy_b.py
new file mode 100644
index 00000000000..1d6aae7679b
--- /dev/null
+++ b/tests/python/render_layer/test_scene_copy_b.py
@@ -0,0 +1,44 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_scene_collections_link(self):
+ """
+ See if scene copying 'LINK_OBJECTS' is working for scene collections
+ """
+ import os
+ ROOT = self.get_root()
+
+ # note: nothing should change, so using `layers_simple.json`
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_simple.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'LINK_OBJECTS',
+ (get_scene_collections,))
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_scene_copy_c.py b/tests/python/render_layer/test_scene_copy_c.py
new file mode 100644
index 00000000000..7d8fb2560ec
--- /dev/null
+++ b/tests/python/render_layer/test_scene_copy_c.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_scene_layers_copy(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene layers
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_full.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'FULL_COPY',
+ (get_scene_collections, get_layers))
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_scene_copy_d.py b/tests/python/render_layer/test_scene_copy_d.py
new file mode 100644
index 00000000000..9b75e57acaa
--- /dev/null
+++ b/tests/python/render_layer/test_scene_copy_d.py
@@ -0,0 +1,43 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def test_scene_layers_link(self):
+ """
+ See if scene copying 'FULL_COPY' is working for scene layers
+ """
+ import os
+ ROOT = self.get_root()
+
+ filepath_layers_json_copy = os.path.join(ROOT, 'layers_copy_link.json')
+ self.do_scene_copy(
+ filepath_layers_json_copy,
+ 'LINK_OBJECTS',
+ (get_scene_collections, get_layers))
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_scene_write_read.py b/tests/python/render_layer/test_scene_write_read.py
new file mode 100644
index 00000000000..553b8fed549
--- /dev/null
+++ b/tests/python/render_layer/test_scene_write_read.py
@@ -0,0 +1,150 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def do_scene_write_read(self, filepath_layers, filepath_layers_json, data_callbacks, do_read):
+ """
+ See if write/read is working for scene collections and layers
+ """
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ with tempfile.TemporaryDirectory() as dirpath:
+ (self.path_exists(f) for f in (filepath_layers, filepath_layers_json))
+
+ filepath_doversion = os.path.join(dirpath, 'doversion.blend')
+ filepath_saved = os.path.join(dirpath, 'doversion_saved.blend')
+ filepath_read_json = os.path.join(dirpath, "read.json")
+
+ # doversion + write test
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
+
+ datas = query_scene(filepath_doversion, 'Main', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_doversion_json = os.path.join(dirpath, "doversion.json")
+ with open(filepath_doversion_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_doversion_json,
+ filepath_layers_json,
+ ),
+ "Run: test_scene_write_layers")
+
+ if do_read:
+ # read test, simply open and save the file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_doversion)
+ self.rename_collections()
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_saved)
+
+ datas = query_scene(filepath_saved, 'Main', data_callbacks)
+ self.assertTrue(datas, "Data is not valid")
+
+ with open(filepath_read_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_read_json,
+ filepath_layers_json,
+ ),
+ "Scene dump files differ")
+
+ def test_scene_write_collections(self):
+ """
+ See if the doversion and writing are working for scene collections
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections,),
+ False)
+
+ def test_scene_write_layers(self):
+ """
+ See if the doversion and writing are working for collections and layers
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections, get_layers),
+ False)
+
+ def test_scene_read_collections(self):
+ """
+ See if read is working for scene collections
+ (run `test_scene_write_colections` first)
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers_simple.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections,),
+ True)
+
+ def test_scene_read_layers(self):
+ """
+ See if read is working for scene layers
+ (run `test_scene_write_layers` first)
+ """
+ import os
+
+ ROOT = self.get_root()
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+ filepath_layers_json = os.path.join(ROOT, 'layers.json')
+
+ self.do_scene_write_read(
+ filepath_layers,
+ filepath_layers_json,
+ (get_scene_collections, get_layers),
+ True)
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()
diff --git a/tests/python/render_layer/test_syncing.py b/tests/python/render_layer/test_syncing.py
new file mode 100644
index 00000000000..80dbe0235e0
--- /dev/null
+++ b/tests/python/render_layer/test_syncing.py
@@ -0,0 +1,119 @@
+# ############################################################
+# Importing - Same For All Render Layer Tests
+# ############################################################
+
+import unittest
+import os
+import sys
+
+sys.path.append(os.path.dirname(__file__))
+from render_layer_common import *
+
+
+# ############################################################
+# Testing
+# ############################################################
+
+class UnitTesting(RenderLayerTesting):
+ def do_syncing(self, filepath_json, unlink_mode):
+ import bpy
+ import os
+ import tempfile
+ import filecmp
+
+ ROOT = self.get_root()
+ with tempfile.TemporaryDirectory() as dirpath:
+ filepath_layers = os.path.join(ROOT, 'layers.blend')
+
+ # open file
+ bpy.ops.wm.open_mainfile('EXEC_DEFAULT', filepath=filepath_layers)
+ self.rename_collections()
+
+ # create sub-collections
+ three_b = bpy.data.objects.get('T.3b')
+ three_c = bpy.data.objects.get('T.3c')
+ three_d = bpy.data.objects.get('T.3d')
+
+ scene = bpy.context.scene
+
+ subzero = scene.master_collection.collections['1'].collections.new('sub-zero')
+ scorpion = scene.master_collection.collections['1'].collections.new('scorpion')
+
+ # test linking sync
+ subzero.objects.link(three_b)
+ scorpion.objects.link(three_c)
+
+ # test unlinking sync
+ if unlink_mode in {'OBJECT', 'COLLECTION'}:
+ scorpion.objects.link(three_d)
+ scorpion.objects.unlink(three_d)
+
+ if unlink_mode == 'COLLECTION':
+ scorpion.objects.link(three_d)
+ scene.master_collection.collections['1'].collections.remove(subzero)
+ scene.master_collection.collections['1'].collections.remove(scorpion)
+
+ # save file
+ filepath_nested = os.path.join(dirpath, 'nested.blend')
+ bpy.ops.wm.save_mainfile('EXEC_DEFAULT', filepath=filepath_nested)
+
+ # get the generated json
+ datas = query_scene(filepath_nested, 'Main', (get_scene_collections, get_layers))
+ self.assertTrue(datas, "Data is not valid")
+
+ filepath_nested_json = os.path.join(dirpath, "nested.json")
+ with open(filepath_nested_json, "w") as f:
+ for data in datas:
+ f.write(dump(data))
+
+ self.assertTrue(compare_files(
+ filepath_nested_json,
+ filepath_json,
+ ),
+ "Scene dump files differ")
+
+ def test_syncing_link(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections and link new objects
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_nested.json')
+ self.do_syncing(filepath_json, 'NONE')
+
+ def test_syncing_unlink_object(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections, link new objects and unlink
+ some.
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers_nested.json')
+ self.do_syncing(filepath_json, 'OBJECT')
+
+ def test_syncing_unlink_collection(self):
+ """
+ See if scene collections and layer collections are in sync
+ when we create new subcollections, link new objects and unlink full collections
+ some.
+ """
+ import os
+ ROOT = self.get_root()
+ filepath_json = os.path.join(ROOT, 'layers.json')
+ self.do_syncing(filepath_json, 'COLLECTION')
+
+
+# ############################################################
+# Main - Same For All Render Layer Tests
+# ############################################################
+
+if __name__ == '__main__':
+ import sys
+
+ extra_arguments = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+ sys.argv = [__file__] + (sys.argv[sys.argv.index("--") + 2:] if "--" in sys.argv else [])
+
+ UnitTesting._extra_arguments = extra_arguments
+ unittest.main()